Что такое Exchange в RabbitMQ?

«Что такое Exchange в RabbitMQ?» — вопрос из категории Брокеры сообщений, который задают на 28% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Exchange в RabbitMQ — это сущность (виртуальный почтовый узел), которая получает сообщения от продюсеров и маршрутизирует их в одну или несколько очередей. Продюсер никогда не отправляет сообщение напрямую в очередь, он публикует его в Exchange, указывая ключ маршрутизации (routing key).

Типы Exchange и их логика маршрутизации

Тип Логика маршрутизации Аналогия
Direct Сообщение попадает в очередь, чей binding key точно совпадает с routing key сообщения. Письмо с конкретным адресом.
Fanout Сообщение копируется во все очереди, привязанные к данному Exchange. Игнорирует routing key. Радиовещание.
Topic Сообщение попадает в очередь, чей binding key соответствует шаблону routing key. Шаблоны используют символы * (одно слово) и # (ноль или несколько слов). Подписка на темы (например, logs.error.*).
Headers Маршрутизация основана на заголовках сообщения, а не на routing key. Привязка указывает условия сопоставления. Фильтрация по атрибутам.

Пример: Объявление и использование Topic Exchange на C

using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();

// 1. Объявляем Topic Exchange
channel.ExchangeDeclare(exchange: "notifications_topic",
                        type: ExchangeType.Topic,
                        durable: true);

// 2. Объявляем очереди и привязываем их с разными binding keys
channel.QueueDeclare(queue: "email_queue");
channel.QueueBind(queue: "email_queue",
                  exchange: "notifications_topic",
                  routingKey: "notifications.email.#"); // Все email-уведомления

channel.QueueDeclare(queue: "critical_queue");
channel.QueueBind(queue: "critical_queue",
                  exchange: "notifications_topic",
                  routingKey: "#.critical"); // Все критические уведомления

// 3. Публикуем сообщение с routing key
var body = Encoding.UTF8.GetBytes("Server is down!");
// Это сообщение попадет в ОБЕ очереди, т.к. ключ "notifications.email.critical"
// соответствует и "notifications.email.#", и "#.critical"
channel.BasicPublish(exchange: "notifications_topic",
                     routingKey: "notifications.email.critical",
                     basicProperties: null,
                     body: body);

Важное правило

Exchange не хранит сообщения. Если опубликованное сообщение не может быть маршрутизировано ни в одну очередь (нет подходящих привязок), оно будет безвозвратно потеряно, если не объявлен Alternate Exchange для обработки таких "сирот".