【问题标题】:RabbitMQ PRECONDITION_FAILED - unknown delivery tagRabbitMQ PRECONDITION_FAILED - 未知的交付标签
【发布时间】:2017-07-22 21:40:22
【问题描述】:

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

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

在 99% 的情况下,这都能完美运行,但我们偶尔会收到错误“RabbitMQ PRECONDITION_FAILED - unknown delivery tag”。这会关闭通道。据我了解,此异常是以下情况之一的结果:

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

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

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

【问题讨论】:

    标签: php rabbitmq amqp


    【解决方案1】:

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

    【讨论】:

    • 尝试编辑以使您的答案更清晰。遇到“编辑队列已满”的问题。尝试用以下 cmets 中的行将其分成段落
    • 他们上面所说的关于确认两次的变体:
    • 存在一种“晦涩”的情况,即您多次确认一条消息,即当您确认一条消息并将多个参数设置为 true 时,这意味着所有以前的消息都发送给您正在尝试确认,也会被确认。
    • 因此,如果您尝试通过将 multiple 设置为 true 来确认“自动确认”的消息之一,那么您将尝试多次“确认”它,因此错误
    • 好的,稍微改进了一下。谢谢
    【解决方案2】:

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      (下面的解决方案)

      在他的博客中引用 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

      【讨论】:

        【解决方案4】:

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

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

        解决办法:no-ack标志设置为false

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

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

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

            【讨论】:

            • 正如@DenisKolodin 回答的那样,我认为首先我们应该检查auto_ack 是否设置为False。如果是真的,我们会在手动确认时得到同样的错误。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-07
            • 2021-10-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-03-16
            相关资源
            最近更新 更多