RabbitMQ PRECONDITION_FAILED -未知的交货标记

zmeyuzjn  于 2022-11-08  发布在  RabbitMQ
关注(0)|答案(6)|浏览(675)

我们有一个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)过期后尝试确认。
我们已经对上述每一种情况实施了保护,但问题仍然存在。
我知道有许多实施细节可能会影响这一点,但在概念层面上,是否存在我们尚未考虑并应处理的任何其他故障情况?或者是否有更好的方法来实现上述功能?

km0tfn4u

km0tfn4u1#

“PRECONDITION_FAILED - unknown delivery tag”通常是由于双重确认、在错误通道上确认或确认不应确认的消息而发生的。
因此,在相同情况下,您将尝试执行basic.ack两次或使用另一个通道执行basic.ack

sigwle7e

sigwle7e2#

(解决方案如下)

引用Jan Grzegorowski的博客:

如果你正在与406错误信息,这是包括在这篇文章的标题挣扎,你可能有兴趣阅读整个故事。

问题

我使用amqplib来连接基于NodeJS的消息处理器和RabbitMQ代理。一切看起来都工作正常,但有时会在日志中显示406(PRECONDINTION-FAILED)消息:

"Error: Channel closed by server: 406 (PRECONDITION-FAILED) with message "PRECONDITION_FAILED - unknown delivery tag 1"

解决方案〈--

保持简单:

  • 您必须按照消息到达系统的相同顺序确认消息
  • 您不能在与消息到达的通道不同的通道上确认消息。如果您违反了这些规则中的任何一条,您将面临406(PRECONDITION-FAILED)错误消息。

Original answer

iugsix8n

iugsix8n3#

如果您将Consumerno-ack选项设置为true(这意味着您不能手动调用ack函数),则可能会发生这种情况:
https://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.consume.no-ack

**解决方案:**将no-ack标志设置为false

mf98qq94

mf98qq944#

他们上面所说的两次攻击的变体:
有一种“模糊”的情况,即您不止一次地对消息进行确认,也就是说,当您将multiple参数设置为true来确认消息时,这意味着您试图确认的消息之前的所有消息也将被确认。
因此,如果您试图通过将multiple设置为true来确认其中一条“自动确认”的消息,那么您将试图多次“确认”它,因此会出现错误,令人困惑,但希望您在阅读几次后理解它。

qqrboqgw

qqrboqgw5#

如果您两次收到相同的消息,则会出现此错误。

ckx4rj1h

ckx4rj1h6#

确保您拥有正确的application.properties:
如果您使用RabbitTemplate而没有任何通道配置,请使用“simple”:

spring.rabbitmq.listener.simple.acknowledge-mode=manual

在这种情况下,如果你使用“direct”而不是“simple”,你会得到同样的错误信息。另一个看起来像这样:

spring.rabbitmq.listener.direct.acknowledge-mode=manual

相关问题