【发布时间】: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 有效地将消息“放到”预取缓冲区的“后面”)。
标签: c# .net rabbitmq message-queue