使用RabbitMQ(Java客户端),有没有办法确定消费期间网络连接是否关闭?

时间:2010-03-18 18:07:44

标签: java rabbitmq amqp

我正在使用Java客户端在RHEL 5.3上使用RabbitMQ。我有2个节点(机器)。 Node1使用Java帮助程序类QueueingConsumer消耗来自Node2上队列的消息。

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客户端上提供某种类型的配置,可用于确定连接是否已消失。关闭Node2上的RabbitMQ服务器将触发ShutdownSignalException,可以捕获该应用程序并且应用程序可以进入重新连接循环。但是,关闭接口不会导致任何类型的异常发生,因此代码将永远等待consumer.nextDelivery()。

我也尝试过使用此调用的超时版本。 e.g。

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会产生相同的结果,但还没有尝试过。

有没有办法配置某种心跳,或者你只需​​编写自定义租约逻辑(例如“我现在在这里”)才能使其正常工作?

2 个答案:

答案 0 :(得分:4)

一般来说,你最好在rabbitmq-discuss邮件列表上发布关于rabbitmq的问题。我们不倾向于跟踪在此之外被问到的问题。

您可以配置心跳,但默认情况下处于禁用状态。你也可以打开TCP Keep Alive。在创建新连接之前在setRequestedHeartbeat上调用ConnectionFactory,或在子类ConnectionFactory上调用configureSocket方法,然后调用socket.setKeepAlive(true)。两者都应该导致连接注意到网络何时死亡。

答案 1 :(得分:3)

关于isOpen方法,在文档中有详细描述:http://www.rabbitmq.com/api-guide.html#shutdown-atomicity

关于关闭:关闭node1或2意味着应用程序正确,而不是RabbitMQ服务器本身?如果另一个应用程序与消息代理断开连接,您为什么要知道任何应用程序?这不是消息传递的重点。

您唯一能做的就是发送带有“强制”参数的消息。这告诉RabbitMQ服务器您希望至少有1个侦听器用于您发送的消息(无论是直接队列还是主题/扇出交换中的某个队列)。如果该消息无法传递到任何队列,则该消息将返回到您的频道并转发给给定的ReturnListener。