.NET Tutorial
Junior7 мин чтенияВопрос 1 из 9

Для чего нужны очереди сообщений: RabbitMQ, Kafka, Azure Service Bus?

Синхронно против асинхронно

Синхронные вызовы

HTTP, ждёт

HTTP, ждёт

упал → ошибка
оформления заказа

Orders API

Email

PDF-счёт

Через брокер

publish, сразу ответ клиенту

Orders API

Брокер
хранит сообщения

Email (обработает,
когда поднимется)

PDF-счёт

Аналитика

Синхронные вызовы

HTTP, ждёт

HTTP, ждёт

упал → ошибка
оформления заказа

Orders API

Email

PDF-счёт

Через брокер

publish, сразу ответ клиенту

Orders API

Брокер
хранит сообщения

Email (обработает,
когда поднимется)

PDF-счёт

Аналитика

Прямые вызовы против очереди
Проблема Синхронно С брокером
Получатель недоступен Ошибка у отправителя Сообщение ждёт в очереди
Долгая операция Клиент ждёт Ответ сразу, обработка фоном
Пик нагрузки Получатель перегружен, отказы Очередь растёт, потребители разбирают в своём темпе
Добавить нового получателя Менять код отправителя Подписаться на событие
Масштабирование обработки Балансировщик, всё синхронно Добавить потребителей (competing consumers)

Типичные сценарии

  • Фоновые задачи: отправка писем и SMS, генерация отчётов, обработка изображений/видео, импорт файлов.
  • Интеграция микросервисов через события (OrderPlaced → склад, оплата, уведомления).
  • Сглаживание нагрузки: всплеск заказов в «чёрную пятницу» — API принимает, воркеры обрабатывают.
  • Потоковая обработка: клики, телеметрия, логи, CDC-изменения БД (Kafka).
  • Надёжные команды между системами с повторами и DLQ.

RabbitMQ

routing key:
order.created

order.*

#

Producer

Exchange
(direct / topic /
fanout / headers)

queue: billing

queue: notifications

queue: audit

Consumer

Consumer ×3
(конкурирующие)

Consumer

routing key:
order.created

order.*

#

Producer

Exchange
(direct / topic /
fanout / headers)

queue: billing

queue: notifications

queue: audit

Consumer

Consumer ×3
(конкурирующие)

Consumer

Модель RabbitMQ: exchange маршрутизирует в очереди
  • Производитель публикует в exchange, тот по bindings и routing key раскладывает копии по очередям.
  • Потребитель получает сообщение, обрабатывает и отправляет ack — только тогда сообщение удаляется. Нет ack (упал) → сообщение будет доставлено снова.
  • Prefetch ограничивает число неподтверждённых сообщений на потребителя (backpressure).
  • Сильные стороны: гибкая маршрутизация, приоритеты, TTL, DLX (dead letter exchange), низкая задержка. Quorum queues и streams — для надёжности и журнального режима.

Kafka

Topic orders (3 партиции)

партиция 0: 0 1 2 3 4 5 ...

партиция 1: 0 1 2 3 ...

партиция 2: 0 1 2 3 4 ...

Producer
key = orderId

Consumer group billing
читает с offset 5, 3, 4

Consumer group analytics
читает с offset 0 — перечитывает историю

Topic orders (3 партиции)

партиция 0: 0 1 2 3 4 5 ...

партиция 1: 0 1 2 3 ...

партиция 2: 0 1 2 3 4 ...

Producer
key = orderId

Consumer group billing
читает с offset 5, 3, 4

Consumer group analytics
читает с offset 0 — перечитывает историю

Модель Kafka: партиционированный журнал
  • Топик разбит на партиции — упорядоченные неизменяемые журналы. Сообщения с одинаковым ключом попадают в одну партицию → порядок по ключу.
  • Сообщения не удаляются после чтения — хранятся по времени/размеру (retention) или компактируются по ключу (compaction).
  • Каждая consumer group хранит свои offset-ы; одна партиция читается одним потребителем группы → параллелизм = число партиций.
  • Сильные стороны: миллионы сообщений в секунду, повторное чтение (replay), потоковая обработка (Kafka Streams, ksqlDB, Flink), CDC (Debezium).

Azure Service Bus

  • Queues (point-to-point) и Topics + Subscriptions (pub/sub с фильтрами).
  • Sessions — упорядоченная обработка по ключу сессии; duplicate detection по MessageId; scheduled messages; встроенная DLQ; транзакции в пределах пространства имён.
  • Полностью управляемый — нет серверов для обслуживания, интеграция с Azure AD/Managed Identity.

Сравнение

RabbitMQ Kafka Azure Service Bus
Модель Брокер с очередями Распределённый журнал Управляемый брокер
После обработки Удаляется (ack) Хранится (retention) Удаляется (complete)
Повторное чтение истории Нет (кроме streams) Да Нет
Порядок В очереди (при одном потребителе) Внутри партиции В сессии
Маршрутизация Гибкая (exchanges) По топикам и ключам Фильтры подписок
Пропускная способность Десятки тысяч msg/s Миллионы msg/s Зависит от тарифа
Задержка Очень низкая Низкая (батчинг) Низкая
Эксплуатация Свой кластер или облако Сложнее (или Confluent Cloud, Event Hubs) Не нужна
Лучше для Задачи, команды, RPC, сложная маршрутизация Потоки событий, аналитика, event sourcing, CDC Корпоративная интеграция в Azure

Работа из .NET

RabbitMQ.Client (низкоуровнево)
var factory = new ConnectionFactory { HostName = "rabbitmq" };
await using var connection = await factory.CreateConnectionAsync();
await using var channel = await connection.CreateChannelAsync();
await channel.QueueDeclareAsync("emails", durable: true, exclusive: false, autoDelete: false);

var body = JsonSerializer.SerializeToUtf8Bytes(new SendEmail("ann@x.uz", "Заказ принят"));
await channel.BasicPublishAsync("", "emails", mandatory: false, new BasicProperties { Persistent = true, MessageId = Guid.NewGuid().ToString() }, body);
Confluent.Kafka
using var producer = new ProducerBuilder<string, string>(new ProducerConfig { BootstrapServers = "kafka:9092", EnableIdempotence = true, Acks = Acks.All }).Build();
await producer.ProduceAsync("orders", new Message<string, string> { Key = order.Id.ToString(), Value = JsonSerializer.Serialize(evt) });

На практике в .NET чаще используют абстракцию над брокером — MassTransit, NServiceBus, Wolverine: сериализация, ретраи, outbox, саги, DLQ и тесты «из коробки» (см. отдельный вопрос).

Вопросы на засыпку

Когда очередь не нужна?

Когда нужен немедленный ответ с результатом (проверка остатка при добавлении в корзину), операции быстрые и надёжные, система небольшая. Брокер добавляет инфраструктуру, eventual consistency и сложность отладки — это должно окупаться.

Почему в Kafka порядок гарантирован только внутри партиции?

Партиции обрабатываются параллельно разными потребителями — глобальный порядок убил бы масштабирование. Если порядок важен для сущности, используйте её идентификатор как ключ сообщения — все её события попадут в одну партицию.

Можно ли использовать Kafka как обычную очередь задач?

Можно, но неудобно: нет подтверждения отдельных сообщений (только offset), нет встроенных DLQ, задержанных сообщений и приоритетов, параллелизм ограничен числом партиций, а одно «тяжёлое» сообщение блокирует партицию. Для очередей задач естественнее RabbitMQ/Service Bus.

Что такое competing consumers?

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

Итог

Брокеры сообщений развязывают сервисы во времени и пространстве, превращают долгие операции в фоновые, сглаживают пики и делают доставку надёжной. RabbitMQ — гибкий брокер задач и команд, Kafka — журнал событий для потоков и повторного чтения, Azure Service Bus — управляемый вариант для облака. Выбирайте по модели использования, а не по моде.