【问题标题】:RabbitMQ Basic Recover Doesn't WorkRabbitMQ 基本恢复不起作用
【发布时间】:2011-09-14 12:27:18
【问题描述】:

我们有一个持久的 RabbitMQ 队列。当消费者从队列中获取项目时,它会处理它然后确认它。如果消费者未能处理该项目,它会打印一个错误,期望有人解决问题并停止。没有发送确认。当消费者重新启动它接收到的项目时,它是队列中的下一个项目,而不是没有 ack 的项目。 Basic.Recover() 没有帮助(使用 .NET 客户端)。 任何如何使它作为队列工作的想法 - 如果它没有被确认,总是得到第一个项目。

【问题讨论】:

    标签: c# rabbitmq


    【解决方案1】:

    消息可以通过两种方式使用 noAck=false 或 noAck=true

    noAck 是 Model.BasicConsume 和 Model.BasicGet 的参数

    当 noAck 设置为 true 时,消息在传递后会自动从队列中删除。如果 noAsk 设置为 false,则仅当您调用 basicAck 时才会删除消息。

    如果 noAck=false 并且您不调用 basicAck 消息将保留,但在您重新启动应用程序(或关闭首先使用它的连接)之前,您不会收到其他消费者的消息。如果您调用 BasicReject,则消息将重新发送给订阅者。

    我希望这会有所帮助。

    【讨论】:

    • 您应该将上面的许多“noAsk”示例改为“noAck”。
    【解决方案2】:

    this entry in the RabbitMQ FAQ。虽然您可能希望 RabbitMQ 将未确认的消息重新排队回到队列的头部(在您的消费者将它们拉下之前它们所在的位置),但正如您所经历的那样,现实可能会有所不同。

    所以并不是Basic.Recover() 不起作用(消息放回队列中以供将来重新处理)只是它没有按您预期的方式工作。

    我脑海中的某件事告诉我,您也许能够通过将预取计数设置为 1 并且在任何时候最多只有一个消费者连接到队列来获得您想要的行为时间,但我不能保证是这样。值得一试。然而,即使它有效,也不能永远依赖于这种情况,并且由于预取计数如此之低,您的消费者的消息/秒性能可能会受到影响。

    【讨论】:

    • 我的计划是将预取计数设置为 1,将失败的消息序列化到一个文件中并确认它。当一个进程再次启动时,它将从该文件中获取第一条消息,对其进行处理,然后继续使用队列。
    • 这在进程被杀死的情况下不起作用。无论如何,兔子都会把它放到队列的末尾。
    【解决方案3】:

    RabbitMQ 似乎已修复此问题的一部分since 2.7.0,因为现在消息将按发布顺序重新排队。虽然如果您的队列有多个订阅者,您可能仍然会收到不符合原始顺序的消息。

    【讨论】:

      【解决方案4】:

      您可以通过拥有一对队列、一个高优先级和一个普通优先级来获得这种行为。将预取计数设置为 1,然后使用 basic.get 在队列之间交替。大多数情况下,优先级队列是空的,但是当您想重新排队时,请再次将消息发布到高优先级队列中。

      这适用于您有多个进程使用消息流的情况,并且一个进程决定退出消息。该消息将几乎立即被另一个进程拾取。

      【讨论】:

      • 我的场景很简单——有一个消费者,消息的顺序很关键,万一意外关机(断电)RabbitMQ把队列的第一条消息放到最后队列。所以我想我应该先使用其他代理来保留第一条消息,直到客户端将其出列。
      • 我在这里问了一个更相关的问题stackoverflow.com/questions/6369190/…
      猜你喜欢
      • 2013-11-06
      • 2014-06-11
      • 2012-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 2016-09-12
      • 1970-01-01
      相关资源
      最近更新 更多