RabbitMQ:消息保持“未确认”

2022-09-01 14:04:01

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

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

可能的原因是什么?


答案 1

未确认的消息意味着它已被您的使用者读取,但使用者从未向 RabbitMQ 代理发送回 ACK 以表示它已完成处理。

我不太熟悉Spring框架插件,但是在某个地方(对于你的消费者),你会声明你的队列,它可能看起来像这样(取自 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

如果您可以发布一些您的消费者代码,那么我也许能够进一步提供帮助...但与此同时,请专门查看BlocktingQueueConsumer:构造函数,您将看到您可以设置ConssentMode,还可以查看nextMessage(),这将返回一个消息对象,其中包含一个名为getDeliveryTag()的方法,这将返回一个Long,这是您将在basicAck上发送回的ID。


答案 2

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

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

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

RabbitMQ Connections

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


推荐