Для чего нужен тип обмена Direct в RabbitMQ?

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

Ответ

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

Аналогия: Это похоже на адресную рассылку писем по конкретному, полному адресу.

Типичные сценарии использования:

  • Распределение задач (Task/Work distribution): Разные типы задач направляются в разные очереди-обработчики.
  • Системы логирования с уровнями: Отдельные очереди для error, warning, info.
  • Событийная маршрутизация: Отправка конкретных событий конкретным подписчикам.

Пример настройки и публикации:

using var channel = connection.CreateModel();
// 1. Объявляем direct exchange
channel.ExchangeDeclare(exchange: "direct_logs", type: ExchangeType.Direct, durable: true);

// 2. Объявляем очереди и привязываем их к exchange с разными binding keys
channel.QueueDeclare(queue: "queue_errors", durable: true, exclusive: false, autoDelete: false);
channel.QueueBind(queue: "queue_errors", exchange: "direct_logs", routingKey: "error");

channel.QueueDeclare(queue: "queue_warnings", durable: true, exclusive: false, autoDelete: false);
channel.QueueBind(queue: "queue_warnings", exchange: "direct_logs", routingKey: "warning");

channel.QueueDeclare(queue: "queue_all_logs", durable: true, exclusive: false, autoDelete: false);
// Одна очередь может быть привязана с несколькими ключами!
channel.QueueBind(queue: "queue_all_logs", exchange: "direct_logs", routingKey: "error");
channel.QueueBind(queue: "queue_all_logs", exchange: "direct_logs", routingKey: "warning");
channel.QueueBind(queue: "queue_all_logs", exchange: "direct_logs", routingKey: "info");

// 3. Публикация сообщений с разными routing keys
var errorBody = Encoding.UTF8.GetBytes("Critical failure!");
channel.BasicPublish(exchange: "direct_logs",
                     routingKey: "error",    // Точное совпадение с ключом
                     basicProperties: null,
                     body: errorBody);
// Это сообщение попадет в: queue_errors И queue_all_logs

var infoBody = Encoding.UTF8.GetBytes("User logged in.");
channel.BasicPublish(exchange: "direct_logs",
                     routingKey: "info",
                     basicProperties: null,
                     body: infoBody);
// Это сообщение попадет ТОЛЬКО в: queue_all_logs

Ключевые отличия от других типов обмена:

  • vs Fanout: fanout игнорирует routingKey и рассылает сообщения во все привязанные очереди. direct — выборочная рассылка.
  • vs Topic: topic позволяет использовать совпадение по шаблону (* — одно слово, # — ноль или несколько слов). direct требует точного совпадения.

Вывод: Direct exchange — это ваш инструмент, когда нужна простая, предсказуемая и эффективная маршрутизация сообщений по чётко заданным правилам.