我们有一个PHP应用程序,它通过WebSocket连接将消息从RabbitMQ转发到连接的设备(PHP AMQP pecl扩展v1.7.1 & RabbitMQ 3.6.6)。
消息是从一个队列数组中使用的(每个websocket连接一个队列),当我们通过websocket接收到消息已被接收的确认时,由使用者确认(这样我们就可以对未在可接受的时间范围内发送的消息重新排队)。这是以非阻塞方式完成的。
在99%的情况下,这是完美的,但偶尔我们会收到一个错误“RabbitMQ PRECONDITION_FAILED - unknown delivery tag“。这关闭了通道。在我的理解中,这个异常是由以下条件之一导致的:
1.消息 * 已 * 被确认或拒绝。
1.尝试通过未传递消息的通道发送确认消息。
1.在消息超时(ttl)过期后尝试确认。
我们已经对上述每一种情况实施了保护,但问题仍然存在。
我知道有许多实施细节可能会影响这一点,但在概念层面上,是否存在我们尚未考虑并应处理的任何其他故障情况?或者是否有更好的方法来实现上述功能?
6条答案
按热度按时间km0tfn4u1#
“PRECONDITION_FAILED - unknown delivery tag”通常是由于双重确认、在错误通道上确认或确认不应确认的消息而发生的。
因此,在相同情况下,您将尝试执行
basic.ack
两次或使用另一个通道执行basic.ack
sigwle7e2#
(解决方案如下)
引用Jan Grzegorowski的博客:
如果你正在与406错误信息,这是包括在这篇文章的标题挣扎,你可能有兴趣阅读整个故事。
问题
我使用amqplib来连接基于NodeJS的消息处理器和RabbitMQ代理。一切看起来都工作正常,但有时会在日志中显示406(PRECONDINTION-FAILED)消息:
解决方案〈--
保持简单:
Original answer
iugsix8n3#
如果您将Consumer的
no-ack
选项设置为true
(这意味着您不能手动调用ack
函数),则可能会发生这种情况:https://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.consume.no-ack
**解决方案:**将
no-ack
标志设置为false
。mf98qq944#
他们上面所说的两次攻击的变体:
有一种“模糊”的情况,即您不止一次地对消息进行确认,也就是说,当您将
multiple
参数设置为true来确认消息时,这意味着您试图确认的消息之前的所有消息也将被确认。因此,如果您试图通过将multiple设置为true来确认其中一条“自动确认”的消息,那么您将试图多次“确认”它,因此会出现错误,令人困惑,但希望您在阅读几次后理解它。
qqrboqgw5#
如果您两次收到相同的消息,则会出现此错误。
ckx4rj1h6#
确保您拥有正确的application.properties:
如果您使用RabbitTemplate而没有任何通道配置,请使用“simple”:
在这种情况下,如果你使用“direct”而不是“simple”,你会得到同样的错误信息。另一个看起来像这样: