Почему бы не использовать только асинхронные сообщения между микросервисами - PullRequest
3 голосов
/ 25 апреля 2020

Почему мы просто не используем asyn c сообщения / события в качестве единственного способа связи в архитектуре микросервисов и удаляем все вызовы sync / http?
Я не могу представить, как syn c может иметь преимущество перед asyn c в любой ситуации.

Представьте себе следующую цепочку вызовов среди 3 сервисов A, B, C:
UI -> A -> B -> C

  • Интерфейс пользователя вызывает A, запрашивая некоторые данные.
  • A должен вызвать B, чтобы получить данные, которые он будет обрабатывать, прежде чем вернуться к UI.
  • Точно так же B должен вызвать C для получения некоторых данных.

Представьте, что все сервисы имеют (конечные) пулы потоков для обслуживания входящих запросов.
Поток в A, который имеет Приняв запрос на подключение от пользовательского интерфейса, отправим HTTP-запрос к B.
Поскольку запрос к B является формой ввода-вывода, этот поток будет прерван до тех пор, пока данные не поступят из A-> B -> C -> B -> А, тратя тем самым нить на долгое время.
Похоже Прерывание ead будет происходить и в остальных сервисах.


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

  • Один пул потоков, который просто запускает потребителей kafka для чтения ответа от нисходящей службы.
  • Один пул потоков для приема нового запроса от восходящей службы.

Рассмотрим следующую последовательность событий:

  • A :: Thread1 получает запрос от пользовательского интерфейса и выдает сообщение ' MsgAB ', инкапсулируя идентификатор запроса вместе с основными данными в очередь сообщений.
  • A :: Thread1 вставит объект соединения запроса в глобальное отображение requestId -> requestObject.
  • A :: Thread1 теперь может обслуживать больше запросов.
  • Аналогично, B выдаст сообщение для C.
  • C создаст ответное сообщение для чтения B, что, в свою очередь, приведет к MsgBA .
  • Теперь A :: Thread2 работает один потребителей кафки будет потреблять e MsgBA инкапсулирует исходный идентификатор запроса.
  • A :: Thread2 ответит на пользовательский интерфейс, используя объект запроса из глобальной карты.

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

Для обработки тайм-аутов мы можем принять следующую стратегию:

  • Мы можем хранить все идентификаторы запроса в любой чувствительной ко времени структуре данных, которая позволяет быстрый доступ и удаление самой старой записи. Куча или LRU-кеш (с использованием стандартной реализации DLL + hashmap) могут быть хорошими вариантами для этой структуры данных.
  • У нас может быть выделенный поток, запускающий планировщик, который проходит через эту структуру данных и отвечает на ошибку времени ожидания все просроченные / истекшие запросы.

Так почему же основанные на HTTP архитектуры микросервисов так распространены?

...