Как работает синхронный вызов в микросервисах?

Читаю книгу Сэма Ньюмена "Создание микросервисов", там есть такая фраза:

With a synchronous blocking call, a microservice sends a call of some kind to a downstream process (likely another microservice) and blocks until the call has com‐ pleted, and potentially until a response has been received.

В русском переводе:

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

Я хочу уточнить - блокируется микросервис (мс) вообще целиком или все-таки только поток, из которого сделан вызов?

Я себе представляю работу так: пусть у нас 2 мс, А и В, сделаны на Spring Web или любом другом веб-фреймворке. Каждого мс по одному экземпляру.

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

Стало быть, если другой пользователь тоже что-то щелкнет, то его запрос тоже будет обслуживаться отдельным потоком, и поэтому сам мс А не блокируется, продолжает нормально работать. Так почему тогда в книге написано, что блокируется микросервис?


Ответы (1 шт):

Автор решения: CrazyElf

Если дальше текст почитать, то там объясняется, что имеется в виду. Если я правильно понял, то речь там не о потоках ОС или программы, а о потоке управления.

Ниже там, например, объясняется, что "Async/Await and When Asynchronous Is Still Blocking", то есть программная асинхронность может и не блокирует поток ОС/программы, но блокирует поток управления. Таким образом, под неблокирующим вызовом там понимается такой вызов, который передаёт какие-то данные в другой модуль/сервис и не ожидает (синхронно либо асинхронно) ничего в ответ. Ответ придёт уже не в этот поток управления, а в какой-то другой обработчик этого микросервиса, который уже этот ответ каким-то образом обработает и на него отреагирует.

То есть противопоставляются две парадигмы работы потока управления (flow control):

  1. Блокирующий запрос:
Послали запрос -> Ожидание ответа (включая асинхронное) -> Реакция на ответ
  1. Неблокирующий запрос:
Послали запрос -> Забыли про запрос, работаем дальше
Пришёл ответ -> Реакция на ответ

Второй вариант можно организовать, например, с помощью брокера сообщений (RabbitMQ, Kafka и т.п.)

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

→ Ссылка