Перейти к содержимому
Модели доставки сообщений

Модели доставки сообщений

Модели доставки определяют, сколько получателей получит сообщение: очередь (queue) доставляет сообщение одному из подписчиков (point-to-point) — для задач и балансировки нагрузки, а топик (topic / pub-sub) рассылает сообщение всем подписчикам — для событий и уведомлений.

Введение: Кому и как

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

В мире брокеров сообщений эти два способа называются очередь и топик.

Модель доставки (Messaging Model) — это способ, которым брокер определяет, кому доставлять сообщение. От этого зависит, сколько получателей получит сообщение, как они его обрабатывают, и как организована маршрутизация.

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

Основные модели

МодельКому доставляетсяСколько получателейТипичное применение
Очередь (Queue)Одному из подписчиков1Распределение задач
Топик (Topic / Pub-Sub)Всем подписчикамNОповещение о событиях

Очередь (Queue)

Как работает

Отправитель кладёт сообщение в очередь. Сообщение достаётся одному из получателей. После того как получатель подтвердил обработку, сообщение удаляется из очереди.

    graph LR
    A[Отправитель] -->|сообщение| Q[Очередь]
    Q -->|сообщение| B[Получатель 1]
    Q -->|сообщение| C[Получатель 2]
    Q -->|сообщение| D[Получатель 3]
  

Особенности

ХарактеристикаЗначение
ПолучателиНесколько, но каждый экземпляр получает разные сообщения
КонкуренцияПолучатели соревнуются за сообщения
ПорядокОбычно FIFO (первым пришёл — первым ушёл)
Балансировка нагрузкиАвтоматическая (кто свободен — тот взял)
Типичный брокерRabbitMQ, AWS SQS, ActiveMQ

Пример: Обработка заказов

    graph LR
    A[Веб-сайт] -->|создан заказ| Q[Очередь заказов]
    Q -->|заказ 1| B[Воркер 1]
    Q -->|заказ 2| C[Воркер 2]
    Q -->|заказ 3| D[Воркер 3]
  

Почему очередь: Заказ должен быть обработан один раз. Не важно, каким воркером.

Когда использовать очередь

СценарийПочему
Распределение задач между воркерамиНужно, чтобы задачу взял один
Балансировка нагрузкиАвтоматически распределяет
Фоновая обработкаКаждое сообщение обрабатывается один раз
FIFO важнаОчередь сохраняет порядок

Топик (Topic / Publish-Subscribe)

Как работает

Отправитель публикует сообщение в топик. Брокер рассылает сообщение всем подписчикам. Каждый подписчик получает копию сообщения.

    graph LR
    A[Отправитель] -->|сообщение| T[Топик]
    T -->|сообщение| B[Подписчик 1]
    T -->|сообщение| C[Подписчик 2]
    T -->|сообщение| D[Подписчик 3]
  

Особенности

ХарактеристикаЗначение
ПолучателиВсе, кто подписан
КонкуренцияНет (все получают все сообщения)
ПорядокМожет не гарантироваться (зависит от брокера)
МасштабированиеЛегко добавить нового подписчика
Типичный брокерKafka, AWS SNS, Redis Pub/Sub

Пример: Событие “пользователь создан”

    graph LR
    A[Регистрация] -->|пользователь создан| T[Топик user.created]
    T -->|событие| B[CRM]
    T -->|событие| C[Биллинг]
    T -->|событие| D[Маркетинг]
    T -->|событие| E[Уведомления]
  

Почему топик: О событии должны узнать все системы.

Когда использовать топик

СценарийПочему
Оповещение о событияхМногие системы должны знать
Событийная архитектураСервисы реагируют на события
Аудит и логированиеВсе события должны быть записаны
Интеграция нескольких системЛегко добавить нового подписчика

Очередь vs Топик

ХарактеристикаОчередьТопик
ПолучателейОдин (на сообщение)Много
КонкуренцияЕстьНет
Балансировка нагрузкиАвтоматическаяНет (все получают всё)
Масштабирование обработкиДобавляем воркеров в очередьДобавляем подписчиков
Типичное применениеЗадачи, фоновая обработкаСобытия, уведомления
ПримерОчередь заказовТопик user.created

Гибридные модели

Очередь с несколькими подписчиками (не путать с топиком)

Некоторые брокеры позволяют нескольким приложениям читать из одной очереди, но каждое сообщение получает только одно приложение. Это всё ещё очередь, а не топик.

Топик с подочередями (Subscription queues)

У каждого подписчика своя очередь. Топик рассылает копии в эти очереди.

    graph LR
    A[Топик] -->|копия| Q1[Очередь подписчика 1]
    A -->|копия| Q2[Очередь подписчика 2]
    Q1 --> B1[Обработчик 1]
    Q1 --> C1[Обработчик 1']
    Q2 --> B2[Обработчик 2]
  

Пример: AWS SNS + SQS. Топик рассылает сообщения в очереди, каждая очередь может обрабатываться несколькими воркерами.

Канал (Channel) — более общее понятие

Некоторые брокеры (RabbitMQ) используют термин “канал” (exchange + queue). Exchange получает сообщение, queue хранит его для получателя.

Выбор модели

Выбираем очередь, если

ПризнакПример
Сообщение должно быть обработано один разПлатёж не должен списаться дважды
Есть несколько обработчиков для балансировкиКто свободен — тот взял
Не важно, кто именно обработаетЛюбой воркер
Важен порядок обработкиFIFO очередь

Выбираем топик, если

ПризнакПример
О событии должны узнать всеВсе системы должны знать о новом пользователе
Легко добавлять новых подписчиковНовая система просто подписывается
Нужен аудитВсе события логируются
Событийная архитектураСервисы реагируют на события

Гибрид, если

ПризнакПример
Нужно и то, и другоеСобытие → очередь → балансировка внутри команды

Пример в реальном проекте

Задача: Интернет-магазин.

СценарийМодельПочему
Обработка заказаОчередьОдин заказ — один обработчик
Оповещение о новом заказеТопикСклад, биллинг, логистика — все должны знать
Отправка emailОчередьМного email, распределяем между SMTP-серверами
Аудит действий пользователяТопикСистема безопасности, аналитика, логи — все подписываются

Архитектура:

    graph TD
    A[Веб-сайт] -->|заказ| Q1[Очередь заказов]
    Q1 --> W1[Воркер 1]
    Q1 --> W2[Воркер 2]
    
    A -->|событие| T[Топик order.created]
    T --> B[Склад]
    T --> C[Биллинг]
    T --> D[Логистика]
    T --> E[Аналитика]
    
    A -->|email| Q2[Очередь email]
    Q2 --> M1[SMTP 1]
    Q2 --> M2[SMTP 2]
  

Особенности разных брокеров

БрокерОчередьТопикОсобенность
RabbitMQДа (queue)Да (exchange + queue)Гибкая маршрутизация
KafkaНет (похоже на топик)Да (topic)Потоковая, лог-ориентированная
AWS SQSДаНетТолько очередь
AWS SNSНетДаТолько топик
RedisДа (list)Да (pub/sub)Легковесный

Распространённые ошибки

Ошибка 1: Использовать очередь для событий

Отправили событие “пользователь создан” в очередь. Только одна система получила событие. Остальные не узнали.

Решение: Для событий — топик.

Ошибка 2: Использовать топик для задач

Опубликовали задачу “обработать заказ” в топик. Все обработчики взяли задачу и обработали 100 раз.

Решение: Для задач — очередь.

Ошибка 3: Путать очередь и топик в AWS

AWS SQS — очередь. AWS SNS — топик. SQS + SNS — гибрид.

Решение: Изучить терминологию брокера.

Ошибка 4: FIFO для топика

Требуют строгий порядок сообщений в топике. Брокер не гарантирует.

Решение: Использовать очередь (FIFO) или добавить порядок через partition key (Kafka).

Ошибка 5: Топик без мониторинга

Подписчики падают, сообщения не доставляются, никто не знает.

Решение: Мониторинг всех подписчиков, алерты.

Резюме

  1. Две основные модели: очередь (одному получателю) и топик (всем подписчикам).

  2. Очередь (Queue): сообщение достаётся одному получателю. Для задач, распределения работы, балансировки нагрузки.

  3. Топик (Topic / Pub-Sub): сообщение доставляется всем подписчикам. Для событий, уведомлений, аудита.

  4. Ключевое различие: сколько получателей получит одно сообщение. Один (очередь) или много (топик).

  5. Гибрид: топик + очередь для каждого подписчика (AWS SNS+SQS).

  6. Выбор модели: задача → очередь, событие → топик.

Проверка знаний

Вопрос 1 из 4
Какие две базовые модели доставки сообщений выделяются в теме?
Что характерно для очереди сообщений?
Что характерно для publish-subscribe?
Какой вопрос помогает выбрать модель доставки?

Вопросы, где были ошибки