繁体   English   中英

RabbitMQ PRECONDITION_FAILED - 未知的交付标签

[英]RabbitMQ PRECONDITION_FAILED - unknown delivery tag

我们有一个 PHP 应用程序,它通过 WebSocket 连接(PHP AMQP pecl 扩展 v1.7.1 和 RabbitMQ 3.6.6)将消息从 RabbitMQ 转发到连接的设备。

消息从队列数组(每个 websocket 连接 1 个)中消费,当我们通过 websocket 收到消息已收到确认时由消费者确认(因此我们可以重新排队未在可接受的时间范围内交付的消息)。 这是以非阻塞方式完成的。

在 99% 的情况下,这可以完美运行,但偶尔我们会收到错误“RabbitMQ PRECONDITION_FAILED - 未知交付标签”。 这将关闭通道。 据我了解,此异常是以下条件之一的结果:

  1. 消息被确认或拒绝。
  2. 尝试通过消息未通过的通道进行确认。
  3. 在消息超时 (ttl) 到期后尝试确认。

我们已针对上述每种情况实施了保护,但问题仍然存在。

我意识到有许多实现细节可能会影响这一点,但在概念层面上,是否还有其他我们没有考虑过并且应该处理的失败案例? 或者有没有更好的方法来实现上述功能?

“PRECONDITION_FAILED - 未知的交付标签”通常是由于双重确认、错误通道上的确认或不应该确认的消息而发生的。

因此,在同一情况下,您要使用另一个通道执行basic.ack两次或basic.ack

(下面的解决方案)

引用 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) 错误消息。

原答案

如果您将Consumer 的no-ack选项设置为true ,则可能会发生这种情况,这意味着您不会手动调用ack函数:

https://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.consume.no-ack

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

如果您确认两次相同的消息,则可能会出现此错误。

确保您拥有正确的 application.properties:

如果您使用 RabbitTemplate 没有任何通道配置,请使用“简单”:

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

在这种情况下,如果您使用“直接”而不是“简单”,您将收到相同的错误消息。 另一个看起来像这样:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM