RabbitMQ:消息仍为“未确认”

时间:2012-08-12 21:37:20

标签: java message-queue rabbitmq amqp

我的Java应用程序向RabbitMQ交换发送消息,然后交换重定向消息到绑定队列。 我在RabbitMQ中使用Springframework AMQP java插件。

问题:消息进入队列,但它保持“未确认”状态,它永远不会变为“就绪”。

可能是什么原因?

2 个答案:

答案 0 :(得分:16)

Unacknowledged消息暗示消​​费者已经读过消息,但是消费者从未向RabbitMQ代理发回ACK,表示已完成处理。

我对Spring Framework插件并不过分熟悉,但在某处(对于您的消费者),您将声明您的队列,它可能看起来像这样(取自http://www.rabbitmq.com/tutorials/tutorial-two-java.html):

channel.queueDeclare(queueName, ....)

然后您将设置您的消费者

bool ackMode = false;
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, ackMode, consumer);

上面的ackMode是一个布尔值,通过将其设置为false,我们明确地告诉RabbitMQ我的消费者会确认它给出的每条消息。如果此标志设置为true,那么您将不会在RabbitMQ中看到未确认的计数,而是只要消费者已将消息读取(即已将其传递给消费者,它将从队列中删除它)。

要确认一条消息,您可以执行以下操作:

QueueingConsumer.Delivery delivery = consumer.nextDelivery();
//...do something with the message...
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); //the false flag is to do with multiple message acknowledgement

如果您可以发布一些消费者代码,那么我可能会进一步提供帮助......但同时请特别注意BlockingQueueConsumer:您将看到的构造函数可以设置{ {3}}并查看nextMessage()这将返回一个Message对象,其中包含一个名为getDeliveryTag()的方法,这将返回一个Long,它是您将在basicAck上发回的ID

答案 1 :(得分:8)

只是为了让消息保持在未确认状态的另一个可能原因加上我的2美分,即使消费者确保使用basicAck方法 -

有时,具有开放RabbitMQ连接的进程的多个实例保持运行,其中一个实例可能导致消息陷入未确认状态,从而阻止消费者的另一个实例重新获取此消息。

您可以访问RabbitMQ管理控制台(对于本地计算机应该可以在localhost:15672上获得),并检查多个实例是否获得该通道,或者当前只有一个实例处于活动状态:

RabbitMQ Connections

找到冗余运行任务(在本例中为java)并终止它。删除流氓进程后,您应该会看到该消息再次跳转到Ready状态。