Может ли у одного exchange в RabbitMQ быть несколько потребителей (consumers)?

«Может ли у одного exchange в RabbitMQ быть несколько потребителей (consumers)?» — вопрос из категории Брокеры сообщений, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, это одна из основных архитектурных возможностей RabbitMQ. Один exchange может рассылать сообщения множеству очередей, к каждой из которых могут быть подключены свои потребители. Механизм рассылки зависит от типа exchange и routing key.

Пример: Fanout Exchange для широковещательной рассылки

using var channel = connection.CreateModel();

// Объявляем fanout exchange (рассылает всем привязанным очередям)
channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout);

// Объявляем и привязываем две независимые очереди
var queue1 = channel.QueueDeclare(queue: "log_queue_1").QueueName;
channel.QueueBind(queue: queue1, exchange: "logs", routingKey: string.Empty);

var queue2 = channel.QueueDeclare(queue: "log_queue_2").QueueName;
channel.QueueBind(queue: queue2, exchange: "logs", routingKey: string.Empty);

// Создаём и запускаем потребителей для каждой очереди
var consumer1 = new EventingBasicConsumer(channel);
consumer1.Received += (model, ea) => { /* Обработка для сервиса A */ };
channel.BasicConsume(queue: queue1, autoAck: true, consumer: consumer1);

var consumer2 = new EventingBasicConsumer(channel);
consumer2.Received += (model, ea) => { /* Обработка для сервиса B */ };
channel.BasicConsume(queue: queue2, autoAck: true, consumer: consumer2);

Ключевые сценарии и типы exchange:

  1. Fanout: Сообщение копируется во все привязанные очереди (широковещание).
  2. Direct/Topic: Сообщение попадает только в очереди, чьи ключи привязки (binding key) совпадают с routing key сообщения (селективная рассылка).
  3. Балансировка нагрузки: Для параллельной обработки сообщений из одной очереди создайте несколько потребителей на эту очередь. RabbitMQ будет распределять сообщения между ними по алгоритму round-robin (при условии, что не включен режим prefetch или ack).

Практический вывод: Exchange выступает как маршрутизатор, позволяя реализовать паттерны "публикатор-подписчик" (Pub/Sub), маршрутизацию и балансировку нагрузки между множеством потребителей.