Rabbitmq Ack 或 Nack,将消息留在队列中
Posted
技术标签:
【中文标题】Rabbitmq Ack 或 Nack,将消息留在队列中【英文标题】:Rabbitmq Ack or Nack, leaving messages on the queue 【发布时间】:2015-04-20 16:15:01 【问题描述】:我一直在玩 RabbitMq.net 和消息确认。 如果消费者能够处理消息,您可以以
的形式发回 ackchannel.BasicAck(ea.DeliveryTag, false);
这会将它从队列中移除。
但是如果消息无法处理怎么办?可能是临时中断,您不希望将消息从队列中删除,然后将其放在后面并继续下一条消息?
我尝试过使用
channel.BasicNack(ea.DeliveryTag, false, true);
但下一轮它仍然收到相同的消息,而不是移动到队列中的下一条消息
我的完整代码是
class Program
private static IModel channel;
private static QueueingBasicConsumer consumer;
private static IConnection Connection;
static void Main(string[] args)
Connection = GetRabbitMqConnection();
channel = Connection.CreateModel();
channel.BasicQos(0, 1, false);
consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume("SMSQueue", false, consumer);
while (true)
if (!channel.IsOpen)
throw new Exception("Channel is closed");
var ea = consumer.Queue.Dequeue();
string jsonified = Encoding.UTF8.GetString(ea.Body);
var message = JsonConvert.DeserializeObject<SmsRecords>(jsonified);
if (ProcessMessage())
channel.BasicAck(ea.DeliveryTag, false);
else
channel.BasicNack(ea.DeliveryTag, false, true);
private static bool ProcessMessage()
return false;
public static IConnection GetRabbitMqConnection()
try
var connectionFactory = new ConnectionFactory
UserName = "guest",
Password = "guest",
HostName = "localhost"
;
return connectionFactory.CreateConnection();
catch (Exception ex)
Console.WriteLine(ex.Message);
return null;
【问题讨论】:
我通过订阅解决了这个问题,然后调用 BasicDeliverEventArgs basicDeliveryEventArgs = subscription.Next(); 如何使用订阅“解决”不断遇到相同消息的问题? NoAck 模式打开(并且服务器自动确认)或发送 Ack 以确认消息的处理 - 如果消息无法以某种有效方式处理但“不应丢失”,则两者都是错误的。如果没有发送 Acks,那么一旦通道关闭,消息就会“重新出现”。我怀疑带有 Subscription 的代码只是使用了更大的 Prefetch 或其他东西..(使用 RabbitMQ > 2.7,您可以 Nack-requeue 有效地将消息“放到”预取缓冲区的“后面”)。 【参考方案1】:这就是我公司的做法:如果一条消息失败(出于任何原因),我们将消息放入一个等待队列中等待 10 秒,然后将其放回队列中进行重试。我们最多循环 10 次,如果消息被 nack 10 次,那么我们认为这是一个我们无法恢复的失败,我们将它放入一个永久的死信队列进行调查。
图表如下:
【讨论】:
如何将消息“放入等待队列”?它不会自动在原始队列中重新排队吗?以上是关于Rabbitmq Ack 或 Nack,将消息留在队列中的主要内容,如果未能解决你的问题,请参考以下文章