RabbitMQ: 消息仍然处于“未确认”状态

28

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

问题是:消息到达队列,但它停留在“未确认”状态,永远不会变成“已准备就绪”。

可能的原因是什么?

2个回答

29

仅提供另一个可能导致消息保持未确认状态的原因,即使消费者确保使用了basicAck方法-

有时,具有打开RabbitMQ连接的进程的多个实例会持续运行,其中一个实例可能会导致消息被卡在未确认状态,从而防止另一个消费者实例重新获取此消息。

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

RabbitMQ Connections

找到多余的运行任务(在这种情况下为Java)并终止它。 删除流氓进程后,您应该看到消息再次跳转到就绪状态。


1
这个答案真是太棒了。几分钟前我的消息还能无缝地发送,但在我重新启动 Mac 后却突然不能发送了,而我并不知道原因。你知道为什么会发生这种情况吗? - Arun T
只是想补充一下,这就是我遇到的情况。我尝试从管理控制台查看队列中的消息,但由于某种原因页面始终无法加载,消息被卡在未确认状态。我希望它们会在过夜时超时,但事实并非如此。上面的建议让我发现了一个与我的用户有关的开放连接。当我强制关闭它时,所有消息都回到了准备就绪状态。幸运的是,这些消息并不重要,所以延迟并不重要。然而,从中恢复是有价值的信息。 - Piercy
1
这在我的情况下也是如此,然而我并不明白其中的原因。 我有两个单独的连接,一个用于发布者,另一个用于消费者。 当我关闭消费者连接并重新建立连接时,消息被传递。 目前对我来说这没有太多意义,因为我期望长时间运行的连接可以正常工作。 我知道我还缺少某些配置,只是还不确定是什么。 - O.MeeKoh

28
未被确认的消息意味着消费者已经阅读了它,但消费者从未向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:在构造函数中,您将看到可以设置AcknowledgeMode,还要查看nextMessage(),这将返回一个包含名为getDeliveryTag()的方法的Message对象,该方法将返回一个Long,这是您将在basicAck上发送回去的ID。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接