Ответ
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 для обработки таких "сирот".