我们有一个持久的RabbitMQ队列。当消费者从队列中获取项目时,它会对其进行处理,然后对其进行确认。如果消费者未能处理该项目,则会打印错误,期望有人解决问题并停止。没有发送确认。当消费者重新启动它时,它接收的项目是队列中的下一个项目,而不是没有ack的项目。 Basic.Recover()没有帮助(使用.NET客户端)。 任何想法如何让它作为一个队列工作 - 总是得到第一个项目,如果它没有被激活。
答案 0 :(得分:3)
可以通过两种方式使用消息noAck = false或noAck = true
noAck是Model.BasicConsume和Model.BasicGet上的参数
当noAck设置为true时,邮件会在传递后自动从队列中删除。如果noAsk设置为false,则只有在调用basicAck时才会删除消息。
如果noAck = false并且您没有调用basicAck,则消息将保留,但在您重新启动应用程序(或关闭首先使用它的连接)之前,您将不会接收其他消费者。如果您致电BasicReject,该消息将被重新发送给订阅者。
我希望这会有所帮助。
答案 1 :(得分:3)
见this entry in the RabbitMQ FAQ。虽然您可能希望RabbitMQ将未经处理的消息重新排队到队列的头部(消费者将其拉下来之前),但实际情况可能会有所不同,正如您所经历的那样。
所以Basic.Recover()
不起作用(消息 重新放回队列以供将来重新处理),只是因为它不能按预期方式工作。
我脑子里的一些东西告诉我,你可能能够通过设置预取计数为1并且最多只有一个消费者连接到任何队列来获得你想要的行为时间,但我无法保证是这样的。值得一试。然而,即使它工作也不依赖于永远保持这种情况,并且如此低的预取计数,消费者的消息/第二次性能可能会受到影响。
答案 2 :(得分:0)
您可以通过拥有一对队列,一个高优先级和一个普通优先级来获得此行为。将预取计数设置为1,然后使用basic.get在队列之间切换。大多数情况下,优先级队列为空,但是当您想要重新排队时,请将该消息再次发布到高优先级队列上。
这适用于您有多个进程正在使用消息流的情况,并且一个进程决定对消息进行挽救。该消息几乎会立即被另一个进程接收。