Что произойдет при публикации сообщения в несуществующий exchange в RabbitMQ?

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

Ответ

Поведение зависит от флага mandatory, который указывает, что делать с сообщением, если его невозможно доставить в очередь.

1. mandatory: false (значение по умолчанию) Сообщение будет безвозвратно отброшено брокером. Отправитель не получит никакого уведомления об ошибке. Это поведение называется "fire and forget" и подходит для сценариев, где потеря отдельных сообщений допустима.

2. mandatory: true Если exchange не существует, брокер вернет сообщение отправителю через механизм Basic.Return. Отправитель должен быть готов обработать это событие.

Практический пример с обработкой возврата:

using RabbitMQ.Client;
using System.Text;

var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();

// 1. Подписываемся на событие возврата сообщения
channel.BasicReturn += (sender, args) =>
{
    var body = args.Body.ToArray();
    var message = Encoding.UTF8.GetString(body);
    Console.WriteLine($"[RETURN] Сообщение возвращено!");
    Console.WriteLine($"  Причина: {args.ReplyText}");
    Console.WriteLine($"  Exchange: {args.Exchange}");
    Console.WriteLine($"  Routing Key: {args.RoutingKey}");
    Console.WriteLine($"  Тело: {message}");
};

// 2. Публикуем сообщение в несуществующий exchange с mandatory=true
var body = Encoding.UTF8.GetBytes("Test Message");
var properties = channel.CreateBasicProperties();
properties.Persistent = true; // Делаем сообщение устойчивым

channel.BasicPublish(
    exchange: "non_existent_exchange", // Несуществующий exchange
    routingKey: "some.routing.key",
    mandatory: true, // Ключевой параметр
    basicProperties: properties,
    body: body);

Console.WriteLine("Сообщение опубликовано. Ожидайте Basic.Return...");

Вывод в консоли будет примерно таким:

Сообщение опубликовано. Ожидайте Basic.Return...
[RETURN] Сообщение возвращено!
  Причина: NO_ROUTE
  Exchange: non_existent_exchange
  Routing Key: some.routing.key
  Тело: Test Message

Рекомендации:

  • Всегда используйте mandatory: true в системах, где критична гарантированная доставка или необходима мгновенная реакция на ошибки маршрутизации.
  • Для повышения надежности комбинируйте это с подтверждениями публикации (Publisher Confirms) и устойчивыми сообщениями (Persistent = true).
  • В продакшене обязательно реализуйте логику повторной отправки или перемещения "отравленных" сообщений в Dead Letter Exchange (DLX).