Как клиент RabbitMQ может определить, когда он теряет соединение с сервером?

Если я подключен к RabbitMQ и прослушиваю события с помощью EventingBasicConsumer, как я могу сказать, был ли я отключен от сервера?

Я знаю, что есть событие выключения, но он не срабатывает, если я отключу сетевой кабель для имитации сбоя.

Я также пробовал событие ModelShutdown и CallbackException на модели, но, похоже, никто не работает.

изменить----- Тот, который я отметил как правильный ответ, но это была только часть решение для меня. Существует также функциональность сердцебиения, встроенная в RabbitMQ. Сервера указывается в файле конфигурации. По умолчанию это 10 минут, но конечно вы можете изменить это.

клиент также может запросить другой интервал для пульса, установив значение RequestedHeartbeat в экземпляре ConnectionFactory.

2 ответов


Я предполагаю, что вы используете библиотеки C#? (но даже так я думаю, что у других есть подобное событие).

вы можете сделать следующее:

public class MyRabbitConsumer
{
  private IConnection connection;

  public void Connect()
  {
    connection = CreateAndOpenConnection();
    connection.ConnectionShutdown += connection_ConnectionShutdown;
  }

  public IConnection CreateAndOpenConnection() { ... }

  private void connection_ConnectionShutdown(IConnection connection, ShutdownEventArgs reason)
  {

  }
}

Это пример, но отмечен ответ, что привело меня к этому.

var factory = new ConnectionFactory
{
    HostName = "MY_HOST_NAME",
    UserName = "USERNAME",
    Password = "PASSWORD",
    RequestedHeartbeat = 30
};

using (var connection = factory.CreateConnection())
{
    connection.ConnectionShutdown += (o, e) =>
    {                       
        //handle disconnect                            
    };

    using (var model = connection.CreateModel())
    {
        model.ExchangeDeclare(EXCHANGE_NAME, "topic");
        var queueName = model.QueueDeclare();

        model.QueueBind(queueName, EXCHANGE_NAME, "#"); 

        var consumer = new QueueingBasicConsumer(model);
        model.BasicConsume(queueName, true, consumer);

        while (!stop)
        {
            BasicDeliverEventArgs args;                       
            consumer.Queue.Dequeue(5000, out args);

            if (stop) return;

            if (args == null) continue;
            if (args.Body.Length == 0) continue;

            Task.Factory.StartNew(() =>
            {
                //Do work here on different thread then this one
            }, TaskCreationOptions.PreferFairness);
        }
    }
}

несколько вещей, чтобы отметить об этом.

Я использую для этой темы. Это захватывает все. Обычно вы хотите ограничить тему.

Я устанавливаю переменную под названием "stop", чтобы определить, когда процесс должен закончиться. Вы заметите, что цикл работает вечно, пока эта переменная не будет истинной.

Dequeue ждет 5 секунд, а затем уходит без получения данных, если есть нет новых сообщений. Это необходимо для того, чтобы мы прослушивали эту переменную stop и фактически выходили в какой-то момент. Измените значение по своему вкусу.

когда приходит сообщение, Я создаю код обработки в новом потоке. Текущий поток зарезервирован только для прослушивания сообщений rabbitmq, и если обработчик слишком долго обрабатывает, я не хочу, чтобы он замедлял другие сообщения. Вам может понадобиться или не понадобиться это в зависимости от вашей реализации. Однако будьте осторожны при написании кода обрабатывать сообщения. Если это займет минуту, чтобы запустить и получать сообщения в субсекунду раз вы будете работать из памяти или, по крайней мере, в серьезных проблемах производительности.