Как архитектуры микросервисных систем позволяют избежать узких мест в сети?


72

Я много читал о микросервисных архитектурах для серверных приложений и удивлялся, как использование внутренней сети не является узким местом или существенным недостатком по сравнению с монолитной архитектурой.

Ради точности, вот мои интерпретации двух терминов:

  1. Монолитная архитектура: одно приложение на одном языке, которое обрабатывает все функциональные возможности, данные и т. Д. Балансировщик нагрузки распределяет запросы от конечного пользователя по нескольким компьютерам, на каждом из которых выполняется один экземпляр нашего приложения.

  2. Микросервисная архитектура. Многие приложения (микросервисы) обрабатывают небольшую часть функциональности и данных. Каждый микросервис предоставляет общий API, доступ к которому осуществляется через сеть (в отличие от межпроцессного взаимодействия или совместной памяти на одном компьютере). Вызовы API в основном размещаются на сервере для создания страницы, хотя, возможно, часть этой работы выполняется клиентом, запрашивающим отдельные микросервисы.

Мне кажется, что архитектура микросервисов использует медленный сетевой трафик, а не более быстрые ресурсы на одной машине (память и диск). Как можно гарантировать, что запросы API через внутреннюю сеть не замедляют общее время ответа?


Внутренняя сеть часто 1 Гбит / с, иногда быстрее. Подумайте о среднем размере ответа JSON от API. Сколько таких ответов можно передать через соединение со скоростью 1 Гбит / с за одну секунду?
Арсений Мурзенко

3
если вы думаете, что вам нужны микросервисы - и вы можете! - две отличные книги для подготовки: amazon.com/Building-Microservices-Sam-Newman/dp/1491950358 и amazon.com/Release-It-Production-Ready-Pragmatic-Programmers/dp/…
Стивен А. Лоу,

@ Основная проблема не в пропускной способности, а в задержке. И если вам нужно туда и обратно, вы будете удивлены, насколько мало фактической пропускной способности вы можете использовать
Стефан Эггермонт

Ответы:


61

Внутренние сети часто используют соединения 1 Гбит / с или быстрее. Оптоволоконные соединения или соединения позволяют значительно увеличить пропускную способность между серверами. Теперь представьте себе средний размер ответа JSON от API. Сколько таких ответов можно передать по соединению 1 Гбит / с за одну секунду?

Давайте на самом деле делать математику. 1 Гбит / с - 131 072 КБ в секунду. Если средний ответ JSON составляет 5 КБ (что довольно много!), Вы можете отправлять 26 214 ответов в секунду по сети только одной парой машин . Не так уж и плохо, не так ли?

Вот почему подключение к сети обычно не является узким местом.

Другим аспектом микросервисов является то, что вы можете легко масштабировать. Представьте себе два сервера, один из которых содержит API, а другой использует его. Если когда-либо соединение становится узким местом, просто добавьте два других сервера, и вы сможете удвоить производительность.

Это когда наши предыдущие 26 214 ответов в секунду становятся слишком маленькими для масштаба приложения. Вы добавляете другие девять пар, и теперь вы можете обслуживать 262 140 ответов.

Но вернемся к нашей паре серверов и сделаем несколько сравнений.

  • Если средний не кэшированный запрос к базе данных занимает 10 мс, вы ограничены 100 запросами в секунду. 100 запросов. 26 214 ответов. Достижение скорости 26 214 ответов в секунду требует большого объема кэширования и оптимизации (если ответу действительно нужно сделать что-то полезное, например, запрос к базе данных; ответы в стиле «Hello World» не подходят).

  • На моем компьютере прямо сейчас DOMContentLoaded для домашней страницы Google произошло 394 мс. после того, как запрос был отправлен. Это менее 3 запросов в секунду. Для домашней страницы Programmers.SE это произошло 603 мс. после того, как запрос был отправлен. Это даже не 2 запроса в секунду. Кстати, у меня есть интернет-соединение со скоростью 100 Мбит / с и быстрый компьютер: многие пользователи будут ждать дольше.

    Если узким местом является скорость сети между серверами, эти два сайта могут буквально выполнять тысячи вызовов различным API при обслуживании страницы.

Эти два случая показывают, что сеть, вероятно, не будет вашим узким местом в теории (на практике вы должны выполнить фактические тесты и профилирование, чтобы определить точное местоположение узкого места вашей конкретной системы, размещенной на определенном оборудовании). Гораздо важнее время, потраченное на выполнение реальной работы (будь то SQL-запросы, сжатие и т. Д.) И отправку результата конечному пользователю.

Подумайте о базах данных

Обычно базы данных размещаются отдельно от веб-приложения, использующего их. Это может вызвать беспокойство: как насчет скорости соединения между сервером, на котором размещено приложение, и сервером, на котором размещена база данных?

Похоже, что бывают случаи, когда скорость соединения становится проблематичной, то есть когда вы храните огромные объемы данных, которые не должны обрабатываться самой базой данных и должны быть доступны прямо сейчас (то есть большие двоичные файлы). Но такие ситуации редки: в большинстве случаев скорость передачи не так велика по сравнению со скоростью обработки самого запроса.

Когда скорость передачи действительно имеет значение, это когда компания размещает большие наборы данных на NAS, и к NAS одновременно обращаются несколько клиентов. Вот где SAN может быть решением. Это, как говорится, это не единственное решение. Кабели Cat 6 могут поддерживать скорость до 10 Гбит / с; Соединение может также использоваться для увеличения скорости без замены кабелей или сетевых адаптеров. Существуют и другие решения, включающие репликацию данных на нескольких NAS.

Забудьте о скорости; думать о масштабируемости

Важным моментом веб-приложения является возможность масштабирования. Хотя реальные характеристики имеют значение (потому что никто не хочет платить за более мощные серверы), масштабируемость гораздо важнее, потому что она позволяет вам использовать дополнительное оборудование при необходимости.

  • Если у вас не очень быстрое приложение, вы потеряете деньги, потому что вам понадобятся более мощные серверы.

  • Если у вас есть быстрое приложение, которое не может масштабироваться, вы потеряете клиентов, потому что не сможете реагировать на растущий спрос.

Точно так же виртуальные машины десять лет назад воспринимались как огромная проблема с производительностью. Действительно, размещение приложения на сервере по сравнению с размещением его на виртуальной машине оказало существенное влияние на производительность. Хотя сегодня этот разрыв намного меньше, он все еще существует.

Несмотря на эту потерю производительности, виртуальные среды стали очень популярными благодаря гибкости, которую они дают.

Как и в случае скорости сети, вы можете обнаружить, что виртуальная машина является фактическим узким местом, и с учетом вашего фактического масштаба вы сэкономите миллиарды долларов, размещая свое приложение напрямую, без виртуальных машин. Но это не то, что происходит с 99,9% приложений: их узкое место находится где-то еще, а недостаток потери нескольких микросекунд из-за ВМ легко компенсируется преимуществами аппаратной абстракции и масштабируемости.


Конечно, мы можем сказать, что ответы JSON невелики, но как насчет их количества ? Я чувствую, что веб-сайт под большой нагрузкой будет иметь больший сетевой трафик в архитектуре микросервиса, чем в монолитной архитектуре (где единственный сетевой трафик идет к / от серверов баз данных). Кэширование может помочь, но для реального времени и / или динамически генерируемого контента я не знаю, как далеко зайдет кэширование.
Джеймс Мишра

@JamesMishra: я отредактировал свой ответ, чтобы решить ваши проблемы.
Арсений Мурзенко

Ваш ответ идеален . Вы отвечали не только на все возражения, которые я могу придумать, вы также отвечали на возражения, о которых я не думал.
Джеймс Мишра

5
Мои 2 цента из реального мира: система, состоящая из очень болтливых микросервисов, может испытывать проблемы с производительностью исключительно из-за дроссельной сети. Кэширование и дизайн на основе Event Stream - ваш друг в таких случаях. Помимо сети, ЦП и памяти, система, основанная на микросервисах, также должна включать устойчивость в свой дизайн: что произойдет, если микросервис не работает? Как вы строите повторные попытки, распределенные транзакции, самовосстановление, мониторинг - я предлагаю поискать «вы должны быть такими высокими, чтобы пользоваться микросервисами»
Судханшу Мишра

4
Пожалуйста, исправьте меня, если я ошибаюсь, но насколько я знаю, если у вас есть сеть 1 Гбит / с, это означает, что вы можете теоретически передавать данные 1 Гбит / с через эту сеть. Независимо от количества подключений. Чем больше количество соединений, тем ниже пропускная способность для каждого соединения. Таким образом, ваш фактический лимит без обновления вашей сети для поддержки более высокой пропускной способности будет 26,214 ответов в секунду. Добавление большего количества серверов не увеличит пропускную способность вашей сети. Если один кластер может выделять такой объем трафика, добавление большего количества серверов, генерирующих еще больше данных, будет загружать вашу сеть.
Себбе

7

Я думаю, что вы слишком много читаете в «микро» часть. Это не значит заменить каждый класс сетевым сервисом, но разделить монолитное приложение на компоненты разумного размера, каждый из которых имеет отношение к аспекту вашей программы. Службы не будут общаться друг с другом, поэтому в худшем случае вы разбили большой сетевой запрос на несколько меньших. Возвращенные данные в любом случае не будут существенно отличаться от того, что вы получаете (хотя вы можете вернуть больше данных и объединить их в клиенте)


3
«Службы не будут общаться друг с другом». Я полагаю, что микросервисы могут иметь общие зависимости (может быть, аутентификацию?), Которые можно разделить на другой микросервис. LDAP, в некотором смысле, является микросервисом аутентификации, и я полагаю, что все другие микросервисы общаются с ним. Или ... аутентификация происходит только один раз? Как каждый микросервис проверяет разрешения на проверку подлинности для предотвращения атак прямого доступа к объектам?
Джеймс Мишра

2
@JamesMishra хорошо .. это зависит. Когда я в последний раз использовал микросервисную архитектуру, каждый сервис был полностью независим от других в целях безопасности (но также и из-за корпоративных проблем). Auth обрабатывается каждым по-разному, хотя и контролируется политикой архитектуры. Тем не менее, нет никаких причин, по которым они не могли бы, например, общаться с auth или просто использовать auth на основе библиотеки. Но .. Я пытался сказать, что они не должны передавать много вызовов между собой, не то, чтобы они не использовали сервисы как клиенты сами.
gbjbaanb

@JamesMishra, auth часто является собственной службой в этих средах, и поэтому каждая служба должна просто использовать это, а не делать полную реализацию самостоятельно.
Пол

2

Путем структурирования вашего кода и доступа к ресурсам таким образом, чтобы результирующая система могла быть достаточно гибкой, чтобы работать как монолитное приложение или как распределенное через конфигурацию. Если вы абстрагируете механизм связи от какого-то общего интерфейса и строите свою систему с учетом параллелизма, вы можете легко оптимизировать все после того, как вы профилировали свою систему и нашли настоящие узкие места.


Пример для объяснения того, что я предполагаю, что означает @mortalapeman: у вас есть java / c # интерфейс IProductAvailibitiy, с которым связаны все потребители IProductAvailibitiy. Существует также класс ProductAvailibitiyImpl, который реализует этот интерфейс, и ProductAvailibitiyMicroservice, который использует ProductAvailibitiyImpl. Потребители могут быть настроены на использование либо локального ProductAvailibitiyImpl, либо удаленного прокси-сервера для ProductAvailibitiyMicroservice
k3b

2

Я хотел бы добавить другую перспективу, из другой отрасли с очень разными предположениями - распределенное (на уровне объекта) моделирование. Концептуально это очень похоже на распределенную видеоигру FPS. Ключевые отличия: все игроки имеют какое-то состояние: где сейчас находится дракон; нет вызовов базы данных; все хранится в оперативной памяти для скорости и низкой задержки, пропускная способность не так важна (но я думаю, вы не можете полностью игнорировать это).

Вы можете рассматривать каждое участвующее приложение как монолит (представляющий все грани игрока) или как микросервис (представляющий всего лишь одного игрока в толпе).

Мои коллеги проявляли интерес к разбивке одного участвующего приложения непосредственно на более мелкие микросервисы, которые могли бы использоваться совместно, например, арбитраж повреждений или вычисления на линии прямой видимости, вещи, которые обычно включаются в моделирование.

Проблема заключается в задержке отправки вызовов и ожидания запросов. Как отмечали другие, пропускная способность в любом случае неактуальна и многочисленна. Но если вычисление прямой видимости идет от 1 мкс до 100 мкс (скажем, из-за очередей в новом микросервисе, совместно используемом всеми приложениями игроков), это огромная потеря (может потребоваться несколько или много вычислений прямой видимости для каждое обновление, несколько обновлений / секунду).

Тщательно продумайте, как работают службы, когда они вызываются и какие данные обмениваются. Наши приложения уже не обмениваются только информацией о положении, они обмениваются мертвой информацией о расплате - я нахожусь в положении x, направляясь в направлении y со скоростью q. И мне не нужно обновлять мою информацию, пока эти предположения не изменятся. Гораздо меньше обновлений, и задержка (хотя все еще проблема) возникает пропорционально реже.

Поэтому, вместо того, чтобы запрашивать услугу с высокой частотой на более высокой частоте, попробуйте уменьшить частоту на:

  1. изменение того, какие данные запрашиваются, и использование локальных вычислений
  2. отправка запроса или триггерных параметров для асинхронного ответа
  3. пакетные запросы
  4. предвидеть запросы и готовить ответ заранее, на спекуляции (в противоположность ленивой оценке)
  5. по возможности избегайте вызова микросервисов другими микросервисами; это усугубляет проблему, очевидно. Я понимаю, что это является стимулом для увеличения микросервисов и в некоторой степени побеждает их, но микросервисы не дружат с задержкой. Может быть, просто признать это и преодолеть это.

Теперь не забудьте проверить свои предположения о вашей системе. Если вас больше беспокоит пропускная способность, чем задержка, или у вас нет общего состояния и т. Д., То обязательно используйте микросервисы там, где они имеют смысл. Я просто говорю, может быть, не используйте их там, где они не имеют смысла.


1

Ваше наивное воображение верно. И часто это не имеет значения. Современные машины быстры. Основные преимущества микросервисной архитектуры проявляются в усилиях и времени на разработку и обслуживание.

И, конечно же, нет правила, согласно которому нельзя использовать общую память или даже физически развертывать несколько служб в одном исполняемом файле. Пока вы разрабатываете, это не зависит от этого.


Процессоры быстрые. Память быстрая. SSD быстрые Но быстро ли работают сетевые карты, маршрутизаторы и коммутаторы? Другой ответ настаивает на этом, но я не уверен.
Джеймс Мишра

Это определенно легко столкнуться с проблемами скорости сети. Запустите один сервис в Сан-Франциско, другой в Амстердаме и используйте их в Сиднее. Задержка - это ключ, а не пропускная способность. Так что не делай этого. И делайте услуги такими большими, как есть смысл
Стефан Эггермонт

1

Как упоминали многие, речь идет не о узких местах сети. Это больше о хрупкости сети. Итак, первый шаг - избежать синхронного общения. Это проще, чем кажется. Все, что вам нужно, это услуги с правильными границами. Правые границы приводят к тому, что сервисы являются автономными, слабо связанными и очень связными. Хороший сервис не нуждается в информации от другого сервиса, он уже есть. Единственный способ, которым хорошие службы общаются, - это через события. Хорошие сервисы также в конечном итоге непротиворечивы, поэтому распределенных транзакций нет.

Способ достижения этого совершенства - сначала определить ваши бизнес-возможности. Бизнес-возможности - это особая бизнес-ответственность. Некоторый вклад в общую стоимость бизнеса. Итак, вот моя последовательность шагов, которую я делаю, когда думаю о границах системы:

  1. Определите бизнес-обязанности более высокого уровня. Там будет несколько из них. Рассматривайте эти услуги как шаги, которые ваша организация должна пройти, чтобы достичь своей бизнес-цели.
  2. Погрузитесь глубже в каждую услугу. Определите сервисы более низкого уровня, включающие родительский сервис.
  3. Наряду с первыми двумя пунктами стоит подумать об услуге связи. Они должны делать это в первую очередь с помощью событий, просто чтобы уведомить друг друга о результатах своего бизнес-процесса. События не должны рассматриваться как конвейеры данных.

Имейте в виду, что бизнес-сервис включает в себя людей, приложения, бизнес-процессы. Обычно только его часть представляется техническим органом.

Это может звучать немного абстрактно, поэтому, вероятно , будет интересен пример идентификации границ сервиса .


0

Просто еще один фактор, чтобы добавить к текущим ответам. С крупнозернистыми услугами . Вы хотите избежать задержки всех вызовов, поэтому вместо 10 вызовов вы делаете вызов, который получает 10 частей данных, необходимых в DTO.

И помните, что микроуслуги не так микро, как думают люди.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.