Как работает синхронный вызов в микросервисах?
Читаю книгу Сэма Ньюмена "Создание микросервисов", там есть такая фраза:
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 шт):
Если дальше текст почитать, то там объясняется, что имеется в виду. Если я правильно понял, то речь там не о потоках ОС или программы, а о потоке управления.
Ниже там, например, объясняется, что "Async/Await and When Asynchronous Is Still Blocking", то есть программная асинхронность может и не блокирует поток ОС/программы, но блокирует поток управления. Таким образом, под неблокирующим вызовом там понимается такой вызов, который передаёт какие-то данные в другой модуль/сервис и не ожидает (синхронно либо асинхронно) ничего в ответ. Ответ придёт уже не в этот поток управления, а в какой-то другой обработчик этого микросервиса, который уже этот ответ каким-то образом обработает и на него отреагирует.
То есть противопоставляются две парадигмы работы потока управления (flow control):
- Блокирующий запрос:
Послали запрос -> Ожидание ответа (включая асинхронное) -> Реакция на ответ
- Неблокирующий запрос:
Послали запрос -> Забыли про запрос, работаем дальше
Пришёл ответ -> Реакция на ответ
Второй вариант можно организовать, например, с помощью брокера сообщений (RabbitMQ, Kafka и т.п.)
В общем, в данном случае вам нужно обратить внимание не на то, что вызов синхронный, а на то, что он блокирующий. Если вы сделаете этот вызов асинхронным или конкурентным (запустите его в отдельном потоке), это всё-равно не сделает этот вызов неблокирующим с точки зрения микросервисной архитектуры, вот в чём тут суть.