RabbitMQ 基本恢复不起作用
我们有一个持久的 RabbitMQ 队列。当消费者从队列中获取项目时,它会对其进行处理然后确认。如果消费者无法处理该项目,它会打印一条错误,期望有人解决问题并停止。没有发送任何确认信息。当消费者重新启动时,它收到的项目是队列中的下一个项目,而不是没有确认的项目。 Basic.Recover() 没有帮助(使用.NET 客户端)。 任何如何使其作为队列工作的想法 - 如果未确认,则始终获取第一个项目。
We have a durable RabbitMQ queue. When consumer gets item from the queue, it processes it and then acknowledges it. If consumer fails to process the item it prints an error expecting someone to fix the problem and stops. No acknowledgement is being sent. When consumer restarts the item it receives is next item in the queue, not the item without ack. Basic.Recover() doesn't help (using .NET client).
Any ideas how to make it work as a queue - always get the first item if it is not acked.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
消息可以通过两种方式使用 noAck=false 或 noAck=true
noAck 是 Model.BasicConsume 和 Model.BasicGet 上的参数。
当 noAck 设置为 true 时,消息在传递后会自动从队列中删除。如果 noAsk 设置为 false 消息,则仅当您调用 basicAck 时才会删除。
如果 noAck=false 并且您不调用 basicAck,则消息将保留,但在您重新启动应用程序(或关闭首先使用它的连接)之前,您不会收到其他使用者的消息。如果您调用 BasicReject,消息将被重新发送给订阅者。
我希望这有帮助。
Messages can be consumed in two ways noAck=false or noAck=true
noAck is a parameter on both Model.BasicConsume and Model.BasicGet
When noAck is set to true messages are automatically removed from the queue after being delivered. If noAsk is set to false messages are only removed when you call basicAck.
If noAck=false and you do not call basicAck the message will remain but you will not receive in on other consumers until you restart the application (or close the connection that consumed it first). If you call BasicReject the message will be redelivered to a subscriber.
I hope this helps.
请参阅RabbitMQ 常见问题解答中的此条目。虽然您可能希望 RabbitMQ 将未确认的消息重新排队回到队列的头部(在您的消费者将其拉下之前它们所在的位置),但正如您所经历的,现实可能会有所不同。
因此,并不是
Basic.Recover()
不起作用(消息已被放回到队列中以供将来重新处理),只是它无法按照您的方式工作预期的。我内心深处的一些想法告诉我,通过将预取计数设置为 1 并在任何时间最多只有一个消费者连接到队列,您也许能够获得您想要的行为,但是我不能保证情况确实如此。值得一试。然而,即使它有效,也不能永远依赖这种情况,并且在预取计数如此低的情况下,您的消费者的消息/秒性能可能会受到影响。
See this entry in the RabbitMQ FAQ. While you may want RabbitMQ to re-queue your unacked messages right back to the head of the queue (where they were before your consumer pulled them down), the reality is likely going to be different, as you've experienced.
So it's not that
Basic.Recover()
doesn't work (the message was placed back on the queue for future reprocessing) just that it doesn't work the way you expected.Something in the back of my mind tells me that you may be able to get the behavior you want by setting a prefetch count of 1 and having at most only one consumer connect to the queue at any time, but I can't guarantee that's the case. It's worth trying. However even if it works it's not something to rely on staying the case forever, and with such a low prefetch count your consumer's messages/second performance will probably suffer.
RabbitMQ 似乎已经修复了这个问题的一部分自 2.7.0 起,因为现在消息将是按发布顺序重新排队。尽管如果队列中有多个订阅者,您仍然可能收到不按原始顺序到达的消息。
RabbitMQ seems to have fixed part of this issue since 2.7.0, as now messages will be requeued in publication order. Although if you have more than one subscriber to a queue, you may still have message arriving out of the original order.
您可以通过拥有一对队列(一个高优先级和一个普通优先级)来实现此行为。将预取计数设置为 1,然后使用 basic.get 在队列之间交替。大多数情况下优先级队列是空的,但是当您想要重新排队时,请再次将消息发布到高优先级队列上。
这适用于以下场景:您有多个进程使用消息流,并且一个进程决定放弃一条消息。该消息几乎会立即被另一个进程接收。
You can get this behaviour by having a pair of queues, one high priority and one normal priority. Set the prefetch count to 1, and then alternate between the queues using basic.get. Most of the time the priority queue will be empty, but when you want to requeue, publish the message again onto the high priority queue instead.
This works in a scenario where you have multiple processes consuming the message stream, and one process decides to bail out on a message. That message will be picked up almost immediately by another process.