Messaging & Queues

Брокеры сообщений

Брокер сообщений — сервис-посредник, который принимает сообщения от одних приложений и доставляет другим, развязывая их во времени и по нагрузке.

Что такое брокер сообщений

Брокер сообщений (message broker) — сервис-посредник, который принимает сообщения от одних приложений и доставляет их другим. Отправитель не знает, кто, где и когда прочитает сообщение: он отдаёт его брокеру и сразу продолжает работу.

Простыми словами это камера хранения между сервисами. Отправитель оставляет посылку и уходит по своим делам, получатель забирает её, когда освободится. Если получатель в этот момент лежит или перегружен, посылка спокойно ждёт на полке, а не теряется и не роняет отправителя.

Зачем он нужен

Без брокера сервис A вызывает сервис B напрямую по HTTP и ждёт ответа. Отсюда три хронические проблемы: B недоступен — падает и A; пик нагрузки — B захлёбывается, а A стоит в ожидании; появился сервис C, которому нужны те же данные — приходится править A.

Брокер разрывает эту связь. A публикует событие «заказ создан» и мгновенно отвечает пользователю; B и C читают событие сами, в своём темпе, и о них A ничего не знает. Очередь заодно работает буфером: при всплеске сообщения копятся у брокера, а не выбивают базу. Такая архитектура называется асинхронной и слабо связанной, и именно она стоит за большинством связок между микросервисами.

Словарь: топик, консьюмер и всё остальное

Топик

Топик (topic, тема) — именованный канал, куда складывают сообщения одного вида: orders.created, user.signup, payments.failed. Продюсер пишет в топик, а не конкретному адресату, и не знает своих читателей. На топик подписываются один или несколько потребителей, и каждый подписчик получает свою копию сообщения — это ключевое отличие топика от очереди, где сообщение достаётся кому-то одному. В Kafka топик дополнительно нарезан на партиции — параллельные части одного потока; в NATS аналог топика называется subject.

Консьюмер

Консьюмер (consumer, потребитель, подписчик) — приложение, которое читает сообщения из топика или очереди и что-то с ними делает: шлёт письмо, списывает деньги, кладёт строку в аналитику. Его противоположность — продюсер (producer, publisher, издатель), который сообщения пишет. Консьюмеров у одного потока может быть много, и работают они в двух режимах: либо делят нагрузку внутри группы (каждое сообщение обрабатывает ровно один из них — так масштабируют обработку), либо читают поток независимо друг от друга (каждый получает всё — так один поток кормит разные подсистемы).

Остальные термины

  • Сообщение (message, событие) — единица передачи: тело (обычно JSON или бинарный формат) плюс заголовки и ключ.
  • Очередь (queue) — буфер, из которого сообщение забирает один потребитель и после обработки оно исчезает.
  • Партиция (partition) — часть топика; определяет и порядок, и предел параллелизма.
  • Offset — номер сообщения в партиции; курсор консьюмера, показывающий, докуда он дочитал.
  • Ack (acknowledgement) — подтверждение обработки. Пока его нет, брокер считает сообщение недоставленным.
  • Consumer lag — отставание консьюмера от продюсера. Главная метрика: растёт lag — не успеваете.
  • DLQ (dead letter queue) — отстойник для сообщений, которые не удалось обработать.

Две модели доставки

Очередь (point-to-point) Топик (publish/subscribe)
Кто получит сообщение Ровно один потребитель Каждый подписчик получает копию
Зачем Раздать работу воркерам Разослать событие всем, кому оно интересно
Пример Сжать видео, отправить письмо «Заказ оплачен» → склад, почта, аналитика
Аналогия Очередь в кассу Радиоэфир

Гарантии доставки

  • at-most-once — не больше одного раза, но можно потерять. Ack выдаётся авансом, до обработки. Годится для метрик и телеметрии.
  • at-least-once — не потеряем, но можем продублировать. Ack после обработки; упал консьюмер между обработкой и ack — сообщение придёт снова. Режим по умолчанию почти везде.
  • exactly-once — ровно один раз. Достижимо лишь внутри контура брокера и с оговорками, стоит заметной производительности.

Практический вывод один: вы почти наверняка живёте на at-least-once, а значит консьюмер обязан быть идемпотентным — повторная обработка того же сообщения не должна менять результат. Обычная реализация: уникальный message_id и проверка «уже обработано» в базе.

Kafka vs RabbitMQ vs NATS

Kafka RabbitMQ NATS
Модель Лог с retention Очереди плюс exchange Pub/sub; JetStream — лог
Сообщение после чтения Лежит до конца retention Удаляется после ack Core: исчезает, JetStream: лежит
Перечитать историю Да Нет Только в JetStream
Кто маршрутизирует Консьюмер выбирает топик и offset Брокер по exchange и routing key Шаблон subject у подписчика
Порядок Внутри партиции Внутри очереди Внутри stream
Пропускная способность Очень высокая Средняя Очень высокая
Задержка Миллисекунды Миллисекунды Микросекунды в core-режиме
Стек и вес JVM, тяжёлая эксплуатация Erlang, средняя Go, один бинарник
Берут ради Потока событий и аналитики Гибкой раздачи задач воркерам Скорости и лёгкости, edge и IoT

Короткое правило выбора. Нужен поток событий, который перечитывают и раздают многим потребителям, — Kafka. Нужна умная раздача задач воркерам с приоритетами, отложенным повтором и маршрутизацией на стороне брокера — RabbitMQ. Нужна лёгкая быстрая шина внутри кластера, request/reply и минимум обслуживания — NATS. Для устройств и слабых каналов есть отдельный протокол — MQTT.

Что ломается на практике

  • Растущий lag. Продюсер быстрее консьюмеров. Мониторить нужно именно lag, а не только «жив ли процесс».
  • Poison message. Сообщение, на котором консьюмер падает всегда. Без DLQ очередь встаёт колом, а повтор с возвратом в ту же очередь даёт бесконечный цикл.
  • Дубликаты. Прямое следствие at-least-once, лечится идемпотентностью.
  • Потеря при рестарте. Очередь и сообщения должны быть durable и persistent, иначе перезапуск ноды сотрёт всё.
  • Брокер как единая точка отказа. Одиночный узел, поставленный ради отказоустойчивости, её же и убивает: нужны минимум три узла и репликация.

По ресурсам брокер — это диск, память и сеть: держат его рядом с потребителями, потому что сетевая задержка между площадками входит в каждое сообщение.

Связанные термины

  • Apache Kafka — брокер-лог, стандарт для потоков событий
  • RabbitMQ — классический брокер очередей с маршрутизацией
  • NATS — лёгкая шина с микросекундными задержками
  • MQTT — протокол обмена сообщениями для устройств и слабых каналов
  • Микросервисы и монолит — архитектура, где брокер обязателен
  • Redis — часто выступает лёгкой очередью в небольших проектах

Готовы запустить GPU-задачу?

Запустить GPU-сервер