RPC over RabbitMQ

May 12, 2022

(todo: del) https://telegra.ph/RPC-over-RabbitMQ-07-22

Привет!

Я сейчас ковыряюсь с легаси проектом, и мне второй месяц не даёт покоя то, что оригинальные авторы запилили RPC over RabbitMQ:

Что здесь происходит:

Это всё происходит в контексте обработки HTTP-запроса
Клиентский код отправляет запрос в очередь
И фактически блокирует обработку запроса в ожидании ответа
Когда сервер складывает ответ, клиент его получает и завершает обработку очереди

Спрашивается нафига тут очередь? На мой взгляд это явный анти-паттерн, который несёт много проблем и мало что даёт взамен.

Пошёл погуглить эту тему. Информации в целом мало, но нашёл официальный туториал как так делать, и пару постов зачем [1], [2].

Давайте разберём плюсы по пунктам. Плюсы Decoupling

In essence, your client does not need to be configured to know where your service lives, only where the broker is. Your client can connect to one broker and gain access to lots of services.

В случае HTTP/REST этого всего можно с тем же успехом добиться с помощью прокси.

Более того, HTTP даёт даже большую расцепленность в этом смысле - в деве я могу упростить себе жизнь и законтачить сервисы напрямую. А вот с очередью так не получиться - дев, не дев, а очередь будь добр поднять. Fault Tolerance

If you want to move your imageCropping service, take it down briefly, deploy it etc, assuming you have multiple instances the client should not notice

Старый-добрый ретрай, который сейчас доступен везде никто не отменял Natural Load balancing

By using a queue instead, your servers will pull off the messages as fast as they can. As consumers, they will “compete” for the messages

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

As any message bus RabbitMQ can connect your services between any DMZs

Тут снова нечем крыть. И снова в общем случае. У нас нет DMZ. Safety

Taking control of machines[...] doesn't allow an attaker to arrange a DoS attack against other services over a message bus

Тут снова нечем крыть. И снова в общем случае. А у нас и так все сервисы торчат в открытом доступе.

Хотя с другой стороны, если если задедосить очерерь, то сляжет вообще всё и разом. Repeated delivery

RabbitMQ keeps messages, repeats delivery if communication breaks. This makes resiliency.

Тут опять же решается ретраем.

Пункты 4 и 5 из второго поста - про нагрузку и эту тему мы уже обсудили.

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

Зато даёт минусы. Минусы

Минус на самом деле один - сложность.

Но проявлений у него несколько. Лишний код

Для реализации RPC пацаны накатали (скопипстили?) тыщу строк нетривиального кода, который у меня прочитать с листа не получается. Лишняя инфраструктура

Для работы мне приходится поднимать очередь. Спасибо докеру, это не сложно, но тем не менее зачем лишняя сущность без которой можно обойтись. Усложнённый дебаг

Выполнить запросы может почти кто угодно, почти откуда угодно.

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

Как минимум с точки зрения читаемости. Я смотрю на код клиента, сервера и шины событий и не вижу ни чего про обработку ошибок. Что если у сервера отвалится подключение к БД? Судя по всему ответ ни кто не отправит и клиент отвалится по таймауту. Так же как и в случае, глупой ошибки, ведущей к NPE. Удачного дебага, надеюсь, что кто-то хотя бы в логи ошибку напишет, хотя в коде я этого не вижу. Выводы

В целом, наверное, использовать REST или RPC over queue для синхронного RPC - это вопрос вкуса.

И на мой вкус использовать очереди сообщений для реализации синхронного RPC стоит только если у вас есть:

Подтверждённая измерениями потребность в эффективном балансировании нагрузки
DMZ и необходимость обращяться "снаружи внутрь"

А в остальных случаях я за REST обеими руками - против лома нет приёма.

Ну и конечно же, очереди это прекрасный инструмент для асинхронной и событийно-ориентированной коммуникации между сервисами.

Report content on this page