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

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

Всем

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

Очередь сообщений (Message Queue, MQ) — способ связать части распределённой системы асинхронно — отправитель кладёт задачу в буфер и сразу продолжает работу, а обработчик забирает её, когда готов. Брокер сообщений — программа, которая хранит эти задачи, следит за порядком и доставкой.

Переход от синхронной пакетной обработки к очередям — эволюция от монолитного batch-процессинга к распределённой асинхронной архитектуре. Раньше один скрипт сам читал файл, трансформировал данные и писал результат; при сбое на 4-м часе из 5 приходилось перезапускать весь прогон. С MQ тяжёлая операция нарезается на миллионы изолированных сообщений, каждое обрабатывается независимо, а масштабирование — запуском дополнительных воркеров.

Когда читать эту статью: после асинхронной коммуникации — здесь теория очередей и брокеров; дальше — идемпотентность и семантика доставки, RabbitMQ и Kafka.

Проблема синхронной связиКак помогает MQ
Потребитель недоступенСообщение ждёт в очереди
Пиковая нагрузкаБуфер сглаживает всплеск
Долгая операция блокирует APIProducer отвечает сразу, работа идёт в фоне
Один сбой останавливает весь batchИзолированные задачи, retry, DLQ

Брокер как посредник

Брокер сообщений — почтальон между программами.

Play ITЗагрузка интерактивного демо…

Одна программа отдаёт ему письмо (сообщение), брокер хранит его, а потом отдаёт другой программе, когда она будет готова.

Представим себе почтовое отделение:

  • мы приходим на почту, отдаём письмо (мы — producer);
  • почта (брокер) кладёт его в ячейку;
  • наш друг (consumer) заходит на почту, когда у него есть время, и забирает письмо.

Упрощённо:

# Программа А (producer)
broker.send("order_queue", {"order_id": 123, "amount": 5000})

# Программа Б (consumer)
message = broker.receive("order_queue")
process_order(message)

Архитектурная модель Producer — Broker — Consumer

Вместо одного скрипта, который сам читает, трансформирует и пишет, система делится на три независимых компонента:

[ Producer ] ──(создаёт задачи)──> [ Message Broker ] ──(распределяет)──> [ Consumers / Workers ]
(инициатор) (очередь) (группа обработчиков)

Producer (продюсер, издатель) — инициатор процесса. Его задача — быстро нарезать тяжёлую операцию на множество мелких изолированных сообщений и "вытолкнуть" их в брокер. Producer тратит на это миллисекунды и свободен: HTTP-ответ пользователю уже отправлен, а обработка идёт в фоне.

Message Broker (брокер сообщений) — умное хранилище (RabbitMQ, Apache Kafka, Apache Pulsar, Amazon SQS). Принимает сообщения, гарантирует сохранность на диске или в памяти и следит за очередностью и маршрутизацией.

Consumer / Worker (потребитель, воркер) — изолированный процесс-обработчик. Берёт из брокера ровно столько сообщений, сколько может переварить (prefetch, batch size), обрабатывает и отправляет отчёт о выполнении (ACK). Несколько воркеров на одной очереди работают как конкурирующие потребители — каждое сообщение достаётся только одному из них.

Связь с интеграционными потоками: outbox, saga и event-driven строятся поверх той же модели "событие → брокер → обработчик".


Что такое очередь

Очередь — структура данных FIFO (First-In, First-Out): первым вошёл — первым вышел. В жизни это очередь в кассу; в коде — операции enqueue (добавить в хвост) и dequeue (извлечь из головы).

Голова → [A] → [B] → [C] ← хвост. После dequeue() первым уйдёт A, затем B, затем C.

Play ITЗагрузка интерактивного демо…

Брокер сообщений использует ту же идею, но на уровне распределённой системы: сообщения — это элементы очереди, а enqueue/dequeue выполняют producer и consumer через сеть. Полная теория структуры (связный список, кольцевой буфер, сложность операций) — в разделе Структуры данных — очередь.

Очередь в памяти vs очередь в брокере

ArrayDeque или collections.deque живут в одном процессе. Message Queue переживает рестарт сервиса, масштабируется на несколько машин и задаёт гарантии доставки — это уже инфраструктурный слой, а не локальная коллекция.


Пакетная обработка и очереди

Пакетная обработка (batch) и очереди сообщений решают схожую задачу — отложить тяжёлую работу от интерактивного пути — но разными способами.

АспектBatch-job на одном сервереОчередь + воркеры
МасштабВертикальный + чанкиГоризонтальный (N consumers)
СбойCheckpoint в jobOffset в Kafka, ACK в RabbitMQ
ПорядокПроще в одном процессеПартиции Kafka, один consumer на очередь
Типичный сценарийНочной ETL, расчёт зарплатыРендер видео, импорт 10 000 файлов, email-рассылка

Как это стыкуется на практике:

  1. Producer нарезает batch на сообщения — вместо "обработать 1 000 000 строк в одном процессе" каждая строка (или chunk из 1000 строк) становится отдельным сообщением.
  2. Воркеры забирают с ограниченным prefetch — не перегружают память, обрабатывают со стабильной скоростью (backpressure).
  3. Checkpoint смещается на уровень сообщения — упал один воркер, остальные продолжают; при at-least-once задача может повториться → нужна идемпотентность.

Пакетная загрузка в интеграциях (batch-окно, расхождение с продом) — 112#batch-etl-load. Оркестрация нескольких шагов batch-конвейера — ETL и оркестрация.


Главные теоретические концепции MQ

При проектировании пакетной обработки через очереди важно понимать три фундаментальных параметра брокеров.

Топология доставки Queue vs Pub/Sub

МодельПоведениеКогда использовать
Очередь (Point-to-Point)Одно сообщение обрабатывает строго один воркер. Если воркер A взял задачу №1, воркер B её уже не увидитПакетная обработка, фоновые job: конкурирующие consumers делят работу
Pub/Sub (издатель / подписчик)Одно сообщение копируется и доставляется всем подписанным системамСобытие "заказ оплачен" → бухгалтерия, склад и доставка получают по копии

В RabbitMQ point-to-point — это очередь с несколькими consumers; pub/sub — fanout или topic exchange. В Kafka pub/sub — подписка consumer group на топик; point-to-point достигают одной группой с несколькими members.

Гарантии доставки (Delivery Guarantees)

В распределённых системах из-за сетевых сбоев невозможно получить идеальную доставку без накладных расходов. Существует три режима:

РежимСмыслПлюсыМинусы
At-most-onceСообщение отправляется, получение не подтверждаетсяМаксимальная скоростьВоркер упал — задача потеряна
At-least-onceБрокер не удалит сообщение, пока воркер не пришлёт ACKСтандарт для тяжёлых пакетовЗадача может выполниться дважды → нужна идемпотентность
Exactly-onceЗадача выполнится ровно один раз, даже при падении сетиНет дубликатов на уровне пайплайнаСложно и дорого: транзакции брокер + БД, EOS в Kafka

На практике устойчивые системы строят на at-least-once + идемпотентный consumer. Подробнее — hub-статья по идемпотентности.

Подтверждение сообщений (ACK / NACK)

Когда воркер забирает задачу, брокер не удаляет её сразу, а помечает как "в процессе" (unacknowledged):

  1. Обработка успешна → воркер шлёт ACK → брокер удаляет сообщение.
  2. Ошибка → NACK или Reject → брокер возвращает задачу в очередь (retry) или перенаправляет в DLQ.

Prefetch (сколько unacked сообщений consumer держит одновременно) и timeout обработки — частые причины "зависших" сообщений; см. FAQ по интеграциям.


Как очереди решают проблемы тяжёлых операций

Горизонтальное масштабирование

Если в очереди скопилось 5 000 000 тяжёлых задач, не нужно увеличивать мощность одного сервера. Запускают ещё 10 или 50 воркеров (Docker, Kubernetes). Они подключаются к тому же брокеру и параллельно разбирают очередь — время обработки сокращается в разы.

Сглаживание пиковых нагрузок

10 000 пользователей одновременно загрузили тяжёлые Excel-файлы — синхронный API может упасть от перегрузки CPU. С MQ producer закидывает 10 000 задач в очередь за секунду, а воркеры разбирают их со стабильной скоростью (например, 50 файлов в минуту). Система не падает — она временно становится асинхронной. Это тот же принцип, что rate limiting на входе, но на стороне обработки.

Изоляция сбоев и Dead Letter Queue

Одна "битая" задача из миллиона не должна останавливать весь пакет:

  1. Воркер пытается обработать сообщение N раз (retry с backoff).
  2. Все попытки неудачны → брокер переносит "токсичное" сообщение в Dead Letter Queue (DLQ) — изолированную очередь для ручного разбора.
  3. Основной поток продолжает работать; разработчик позже смотрит DLQ и чинит данные или код.

Паттерн связан с circuit breaker и инженерией устойчивости: изолировать сбой, не ронять весь контур.


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

Вы наверняка сталкивались с термином "брокер" на бирже? Между системами нужна асинхронная доставка большого количества сообщений через посредника-агента.

Брокер сообщений — программное обеспечение или система, которая управляет обменом данными между приложениями. Основная задача: принять сообщение от producer, сохранить или маршрутизировать его и доставить consumer (иногда с преобразованием формата по правилам интеграции).

Producer отправляет сообщение и продолжает работу, не дожидаясь ответа. Брокер гарантирует доставку при сбоях (очереди, подтверждения, репликация) и распределяет нагрузку между несколькими consumers.

Среди брокеров различают RabbitMQ (модель очередей и AMQP), Apache Kafka (лог топиков и партиций), ActiveMQ (классический JMS-брокер), IBM MQ. Redis чаще — кэш, но для интеграций иногда используют Pub/Sub или Streams — это ближе к лёгкой очереди, чем к enterprise-шине с тем же набором гарантий, что у RabbitMQ или Kafka. Практика Redis — Redis в интеграции и кэшировании.

Единица обмена — сообщение (запись, event). В RabbitMQ / IBM MQ / ActiveMQ сообщения лежат в очередях; в Kafka пишут в топик, разбитый на партиции (топик — канал, а не одно сообщение).


RabbitMQ и Kafka в контексте пакетов

Оба инструмента работают с сообщениями, но внутренняя теория принципиально отличается:

ПодходRabbitMQKafka
ФормулаSmart Broker, Dumb ConsumerDumb Broker, Smart Consumer
ХранениеСообщение удаляется после успешного ACKСообщения хранятся на диске днями — это лог, не transient-очередь
Кто помнит прогрессБрокер (очередь опустошается)Consumer хранит offset — где читает в партиции
Сильная сторонаКлассические задачи: email, рендер, заказыПакетная аналитика, Big Data, стриминг миллионов событий/с

RabbitMQ сам следит, кому какое сообщение дать, считает подтверждения и удаляет после ACK. Отлично подходит для "отрендерить видео", "отправить письмо", "обработать заказ".

Kafka — распределённый непрерывный лог записей. Чтение — последовательное сканирование диска; несколько consumer group могут читать один топик независимо. Идеальна для потоковой аналитики и event log.

Сравнительная таблица

КритерийRabbitMQKafka
АрхитектураОчереди (queues)Топики (topics) с партициями (partitions)
Модель работыProducer → Exchange → Queue → ConsumerProducer → Topic → Partition → Consumer
УпорядоченностьПорядок в пределах одной очередиПорядок только внутри одной партиции
Состояние данныхДо доставки или TTLНа диске заданное время (например, 7 дней)
ПроизводительностьДо десятков тысяч msg/sДо миллионов msg/s
ЗадержкиНизкие (прямая передача через очереди)Выше (партиционирование, commit offset)
РесурсыМеньше для небольших нагрузокБольше памяти и диска
МасштабируемостьКластер сложнее настроитьЛегко: брокеры + партиции
Гарантия доставкиAt-least-once при ACK и durable-очередяхAt-least-once; exactly-once при согласованной настройке
МаршрутизацияСложные правила через exchangesТопики и партиции
СценарииФоновые задачи, микросервисы, уведомленияЛогирование, мониторинг, IoT, аналитика

Постановка "отправить письмо" в очередь — только первый шаг; доставка, bounces и отписки — отдельный контур: email-рассылка как распределённая система.


Как выбрать технологию под задачу

Выбор зависит от бизнес-сценария и требований к доставке:

  • RabbitMQ — фоновые задачи, сложная маршрутизация через exchange, классические job-очереди;
  • Kafka — потоковая аналитика, event log, долгое хранение событий, replay;
  • Redis — быстрый слой для кэша, rate limit и лёгких очередей без жёстких гарантий.

В реальной архитектуре инструменты часто работают вместе — Kafka переносит события между доменами, RabbitMQ — короткие task-очереди, Redis ускоряет чтение. Сквозной пример — практика 134.


См. также

Продолжение в разделе "Инфраструктура и безопасность" — брокеры сообщений, RabbitMQ и Kafka. Брокеры в экосистеме MSA — вместе с БД, контейнерами и мониторингом.