这似乎是一个简单的问题,但我很难找到明确的答案.如果在RabbitMQ 3.6.1中我有一个如下所示的队列:
5 4 3 2 1 <= head
Run Code Online (Sandbox Code Playgroud)
我消费消息1,然后做:
channel.BasicReject(ea.DeliveryTag, true);
Run Code Online (Sandbox Code Playgroud)
将在1队列的末尾或在队列的头端了(假设为简单起见,没有其他人在消费的时候队列的缘故)?那么我最终会得到:
1 5 4 3 2 <= head
Run Code Online (Sandbox Code Playgroud)
要么:
5 4 3 2 1 <= head
Run Code Online (Sandbox Code Playgroud)
无论如何要控制它(一种方法是收听消息并完全重新发布它我想)?我实际上想要第一种情况,因为我拒绝,1因为处理该消息所需的特定资源当前不可用.所以我想把它扔回队列以便稍后处理(当资源可用时)或者被其他人(有资源可用)接收.但是我不想再把它扔回去继续捡起它.
小智 7
明确回答像我一样迟到这个问题并且需要非“阅读文档”答案的人:
\n\n\n当消息重新排队时,如果可能的话,它将被放置到其队列中的原始位置。如果不是(由于多个消费者共享一个队列时来自其他消费者的并发传递和确认),消息将被重新排队到更靠近队列头的位置。-来自Rabbitmq的官方网站-rabbitmq.com/nack.html \xe2\x80\x93 smc
\n
使用您的示例扩展(当前)最佳答案的评论
\n\n\n我有一个看起来像这样的队列:
\n
5 4 3 2 1 <= head
\n\n我消费了消息1
\n
现在队列是:5 4 3 2 <= head
\n\n然后做:
\nchannel.BasicReject(ea.DeliveryTag, true);
你的结果将与最初的相同,
\n5 4 3 2 1 <= head
如果你只有一个消费者。对于多个消费者,可能会出现以下情况:
\n最初的:5 4 3 2 1 <= head
消费者1接受消息:5 4 3 2 <= head
消费者 2 接受消息,而消费者 1 正在处理:5 4 3 <= head
消费者 1 决定拒绝并重新排队,结果是:5 4 3 1 <= head
我会说答案在这里,我会引用一部分:
可以使用具有requeue参数(basic.recover,basic.reject和basic.nack)或由于保留未确认消息而关闭通道的AMQP方法将消息返回到队列。这些情况中的任何一种都会导致对于2.7.0之前的RabbitMQ版本,消息在队列的后面重新排队。从RabbitMQ版本2.7.0开始,即使在存在重新排队或关闭通道的情况下,消息也始终按发布顺序保留在队列中。
因此,我们可以假设以这种方式实施RMQ,直到消息被确认之前,它们不会从队列中被删除(实际上已删除),它们可能具有ACKed标志或其他内容。