NilHex
@NilHex
Developer

Какию реализации RPC и Message Bus стоит рассмотреть для микросервисной архитектуры?

Имеется большой проект в сфере трейдинга, имеющий SOA подобную архитектуру. На текущий момент все это выглядит как некоторое количество микросервисов, содержимое которых инкапсулированно друг от друга: к примеру один микросервис не имеет прямого доступа в базе данных другого. Большая часть сервисов написана на python, подразумеваются сервисы и на go. Все это крутится на кластере docker swarm.
Интерфейсом взаимодействия сервисов выступает RabbitMQ, через который реализуется сразу и удаленный вызов процедур и обмен данными.
Далее опишу основные кейсы использования такого взаимодействия:
1. Запрос данных:
Сервис A посылает сообщение сервису B, идет дальше выполнять свою логику, по завершении блокирует рантайм, ожидая ответа в callback очереди.
Пример: запрос актуальных цен стоков для подсчета стоимости активов
2. Односторонний вызов удаленный процедуры:
Сервис A посылает сообщение сервису B и идет дальше выполнять свою логику.
Пример: запрос на отправку уведомления на email
3. Инициализация события для множества сервисов:
Сервис A отсылает сообщение в очередь, которую слушают сервисы B, C, D. Сообщение удаляется из очереди после того как все сервисы сообщили о его прочтении.
Пример: событие регистрации нового пользователя в системе, по которому в разных сервисах для него создаются различные записи

Реализовано это сейчас с помощью собственной библиотеки на основе pika.

Имеющиеся проблемы:
1. Скорость: зачастую приходится через эту шину гонять довольно большие данные (к примеру годовые графики стоков).
2. Ресурсы: RabbitMQ все хранит в ОЗУ, особенно больно становится когда происходят сбои в процессах подписчиков callback очередей и данные висят некоторое время в памяти RabbitMQ. Был случай когда из-за бага в таком процессе под нагрузкой случилось переполнение памяти и нода повисла.
3. Необходимость собственной высокоуровневой библиотеки, в первую очередь для реализации событийно-ориентированной модели (продолжительный поиск не дал подходящих библиотек).

Очевидные способы решения:
1. Прямые запросы к данным других сервисов:
Не подходит, так как имеется желание инкапсулировать сервисы, плюс многие данные подразумевают обработку перед отправкой
2. Использование HTTP API для обмена данными:
Не подходит, так как в таком случае ассинхронность придется реализовывать в бизнес логике сервиса и удерживать соединение. В случае если на стороне получателя возникнет сбой, данные будут потеряны

Конечная архитектура взаимодействия видится событийно-ориентированной, большая часть рассчетов, подрузок данных с внешних сервисов происходит в фоне по некоторым событиям или расписанию, клиенту данные отдаются преимущественно из кешей.
В качестве интерфейса клиент-сервер пока используется JSON REST API, имеются мысли по миграции на websocket с GraphQL внутри так как нужен реалтайм и реактивность.

Возвращаясь к вопросу в заголовке уточню, что ищу как подходящие под кейс библиотеки/фрейморки для AMQP, так и другие стеки. Так же с удовольствием почитаю комментарии и советы относительно всей архитектуры в целом и ее возможных альтернатив. В конце концов в сети не так много информации и кому-то это может быть полезно.
  • Вопрос задан
  • 574 просмотра
Пригласить эксперта
Ответы на вопрос 2
yellow79
@yellow79
Senior Software Engineer
На мой взгляд у вас RabbitMQ является самым узким местом, мало того, что он сам по себе медленный, так он у вас ещё и избыточно перегружен. Необходимо максимально избавиться от него.

Для выполнения удалённых процедур уже давно придуман RPC или более продвинутый его аналог GRPC, который гоняет данные в бинарном формате, что сокращает размеры запросов и увеличивает скорость передачи, что так же может пригодиться вам для реализации запроса за данными. Думается если вы первые два пункта уберёте, кролику станет значительно легче и возможно на этом можно будет остановиться, если нет, то возможно стоит отказаться от него в пользу Nats, посмотрите, он может вас сильно порадовать производительностью. Ну или можно посмотреть в сторону Redis, он так же превосходит кролика в реализации очередей и на мой взгляд отлично подходит для реализации событийно-ориентированной архитектуры.
Ответ написан
@scor2k
Как вариант, не гонять через RabbitMQ весь запрашиваемый и отправляемый объем данных, а отправлять только идентификатор. Сами данные хранить в базе.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы