Очереди сообщений (2025)

Навроцкий Артем

Очереди сообщений (2025)

Навроцкий Артем

Зачем нужны очереди сообщений?

Публикация/подписка (push)

Клиент подписывается на события. Брокер отправляет в клиента события по мере поступления.

Опрос брокера (pull)

Клиент периодически проверяет состояние очереди.

Опрос с ожиданием (pull + long pulling)

Клиент периодически проверяет состояние очереди. Если сообщений нет, то запрос ждёт их какое-то время.

Позволяет получить плюсы pull и push подходов.

Гарантии доставки сообщений

Мир не идеален

Не больше одного раза (at most once)

  1. Взять сообшение из очереди
  2. Удалить из очереди
  3. Отправить сообщение
  4. Забыть про него

Хотя бы один раз (at least once)

  1. Взять сообшение из очереди
  2. Отправить сообщение
  3. Дождаться подтверждения о получении
  4. Удалить сообщение
  5. Если подтверждения не было, перейти к п. 1

Хотя бы один раз (at least once)

На стороне брокера

  1. Взять сообшение из очереди
  2. Отправить сообщение
  3. Дождаться подтверждения о получении
  4. Удалить сообщение
  5. Если подтверждения не было, перейти к п. 1

Хотя бы один раз (at least once)

На стороне клиента

Потребитель должен быть ровно один.

Ровно один раз (exactly once)

Ровно один раз (exactly once)

Задача двух генералов

Ровно один раз (exactly once)

Попытка достижения нужного результата

Ограничение: потребитель должен быть один.

Ровно один раз (exactly once)

Удалось гарантировать доставку, но гарантировать обработку ровно один раз все равно невозможно:

  1. Есть список полученных сообщений
  2. Берем сообщение
  3. Выполняем работу
  4. Удаляем сообщение

Решает проблему идемпотентность выполняемой работы, но она не всегда достижима.

Идемпотентность

Идемпотентность
Свойство объекта или операции при повторном применении операции к объекту давать тот же результат, что и при первом

Топологии очередей

Один брокер

МасштабируемостьДоступностьНадежность
ОтсутствуетНизкаяНизкая

Несколько брокеров

МасштабируемостьДоступностьНадежность
ЕстьВысокаяСредняя

Несколько брокеров + дублирование

МасштабируемостьДоступностьНадежность
ЕстьВысокаяВысокая

Требуется идемпотентность или дедупликация

Репликация

МасштабируемостьДоступностьНадежность
ЕстьВысокаяВысокая

Проблему надёжности для схемы с несколькими брокерами можно решить через репликацию.

Видеоплатформа

Загрузка нового видео пользователем

Что может пойти не так?

Что делать?

На стороне API Gateway:

Архитектура с использованием очередей

Архитектура с использованием очередей

Популярные очереди сообщений

Популярные очереди сообщений

On-premises

  • RabbitMQ
  • Apache Kafka
  • NATS
  • ZeroMQ

На основе СУБД

  • PgQueue
  • Redis

Облачные

  • Amazon SQS
  • Yandex MQ
  • CloudAMQP (RabbitMQ)

RabbitMQ

RabbitMQ

RabbitMQ

RabbitMQ

Типы Exchange

Direct
Прямая отправка сообщений в одну или несколько очередей с совпадающим значением ключа маршрутизации (routing key)
Topic
Сообщение отправляется в очереди по значению ключа маршрутизации (routing key), заданного по шаблону
Fanout
Все сообщения отправляются во все очереди независимо от ключа маршрутизации
Headers
Маршрутизация по атрибутам, заданным в заголовке сообщения

Масштабирование RabbitMQ

Масштабирование в основном вертикальное, но возможно очереди распределить между узлами

Kafka

Kafka

Kafka

Масштабирование Kafka

Что выбрать?

Коммуникация между сервисами

NATS

Сложный роутинг

А точно нужно?

Во всех остальных случаях

Kafka

Dead letter queue (repair queue)

CQRS

Command and Query Responsibility Segregation

Подход к проектированию системы, который разделяет операции чтения и записи данных на две отдельные модели.

CQRS

CQRS

CQRS

CQRS

Transactional outbox

  1. Получили сообщение
  2. Создали во внутренней базе запись со статусом проверки
  3. Проверка прошла
  4. Отправили сообщение в следующую очередь
  5. Удалили запись

Transactional outbox

  1. Получили сообщение
  2. Создали во внутренней базе запись со статусом проверки
  3. Проверка прошла
  4. В транзакции удалили запись и сделали запись в другой таблице
  5. Отдельный процесс читает вторую таблицу, отправляет сообщения и удаляет записи (at least once)

Диагностика очередей

Мониторинг очередей

  1. Количество необработанных сообщений. Нормальное состояние - очередь пустая
  2. Время
    • Полное время обработки сообщения (QoS)
    • Время обработки потребителем
  3. Количество повторов и отказов
  4. Количество сообщений

Логирование сообщений

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

Проектируем ленту новостей

Ссылки

Спасибо за внимание!