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

Ответ

Да, это одна из основных архитектурных возможностей 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), маршрутизацию и балансировку нагрузки между множеством потребителей.

Ответ 18+ 🔞

Да ты что, блядь! Так это же одна из главных фишек RabbitMQ, я тебе щас объясню, как оно работает, только не обосрись от восторга.

Смотри, представь себе почтовое отделение, только на минималках. Exchange — это такой главный сортировщик, долбоёб с корзиной писем. А очереди — это ящики, куда он эти письма кидает. Так вот, этот сортировщик может хуярить одно и то же письмо сразу в кучу разных ящиков! И к каждому ящику стоит свой мужик (consumer) и ждёт, когда ему работу подкинут.

Вот тебе пример на C#, как сделать вещание на всю деревню (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 "logs" — и оба потребителя его получили, каждый из своей очереди. Красота, да?

А вообще, у этого сортировщика-exchange есть несколько режимов работы, как у дрели:

  1. Fanout (Оратор): Включил — и пиздит всем подряд, кто в зоне доступа. Без разбора. Вещает как сумасшедший.
  2. Direct/Topic (Придирчивый мудак): Этот уже умный. Он смотрит на routing key (типа адрес на конверте) и binding key (надпись на ящике). Кидает письмо только в те ящики, где адрес совпал. Хочешь — только бухгалтерии, хочешь — только курьерам.
  3. Балансировка нагрузки (Работа в поле): А это когда на один ящик нанимаешь не одного, а пятерых грузчиков. RabbitMQ будет сам раскидывать письма между ними по кругу, чтобы никто не простаивал и не надрывался. Главное — не давать им слишком много работы в одни руки (это настройка prefetch).

Короче, суть в чём: Exchange — это мозг и рот всей системы. Через него можно и всем сразу орать (Pub/Sub), и избирательно шептать (роутинг), и работу между бригадами распределять. Мощная хуйня, если головой думать, как её применить.