Используя RabbitMQ (клиент Java), существует ли способ определить, закрыто ли сетевое соединение во время потребления?

Я использую RabbitMQ для RHEL 5.3 с помощью Java-клиента. У меня есть 2 узла (машины). Node1 потребляет сообщения из очереди на Node2, используя класс вспомогательного класса Java QueueingConsumer.

QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume("MyQueueOnNode2", noAck, consumer);
while (true)
{
   QueueingConsumer.Delivery delivery = consumer.nextDelivery();
   ... Process message - delivery.getBody()
}

Если интерфейс отключен на Node1 или Node2 (например, ifconfig eth1 down), клиент (выше) никогда не знает, что сети больше нет. Предоставляет ли RabbitMQ некоторую конфигурацию на Java-клиенте, которая может использоваться для определения того, прошло ли соединение. Выключение сервера RabbitMQ на Node2 вызовет исключение ShutdownSignalException, которое можно поймать, и приложение может перейти в цикл повторного подключения. Но сведение интерфейса не приводит к возникновению какого-либо типа исключения, поэтому код будет ждать навсегда .nextDelivery().

Я также пробовал использовать таймаут-версию этого вызова. например.

QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume("MyQueueOnNode2", noAck, consumer);
int timeout_ms = 30000;
while (true)
{
   QueueingConsumer.Delivery delivery = consumer.nextDelivery(timeout_ms);
   if (delivery == null)
   {
      if (channel.isOpen() == false)             // Seems to always return true
      { throw new ShutdownSignalException(); }
   }
   else
   {
     ... Process message - delivery.getBody()
   }
}

но кажется, что это всегда возвращает true (даже если интерфейс не работает). Я предполагаю, что регистрация для ShutdownListener в соединении даст те же результаты, но пока не пробовала.

Есть ли способ настроить какое-то свое сердцебиение, или просто нужно написать индивидуальную логику аренды (например, "Я здесь сейчас" ), чтобы заставить это работать?

Ответы

Ответ 1

В общем, вам гораздо лучше задавать вопросы относительно rabbitmq в списке рассылки rabbitmq-discuss. Мы не склонны отслеживать вопросы, задаваемые за пределами этого.

У вас есть сердцебиение, которое вы можете настроить, хотя по умолчанию оно отключено. Вы также можете включить TCP Keep Alive. Либо вызовите setRequestedHeartbeat в ConnectionFactory перед созданием нового соединения, либо подкласса ConnectionFactory, переопределите метод configureSocket и вызовите socket.setKeepAlive(true). Оба должны привести к обнаружению соединения, когда сеть умирает.

Ответ 2

Относительно метода isOpen, который хорошо описан в документах: http://www.rabbitmq.com/api-guide.html#shutdown-atomicity

Что касается закрытия: при выключении узла1 или 2 вы имеете в виду право приложения, а не сервер RabbitMQ? Почему вы хотите узнать о любом приложении, если другое приложение отключится от брокера сообщений? Это не точка обмена сообщениями.

Единственное, что вы можете сделать, это отправлять сообщения с обязательным параметром. Это сообщает серверу RabbitMQ, что вы ожидаете по крайней мере 1 прослушивателя для отправленного сообщения (будь то прямая очередь или какая-то очередь в обмене тема/разветвление). Если сообщение затем не может быть доставлено в какую-либо очередь, сообщение вернется к вашему каналу и перенаправляется на заданный ReturnListener.