默认情况下,EasyNetQ的消息处理过程中,如果throw exception,那么,依然是认为消息已经送达,不会再次推送,为了让RabbitMQ再次推送,可以这么实现:
public sealed class AlwaysRequeueErrorStrategy : IConsumerErrorStrategy
{
public void Dispose()
{
}
public AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
{
return AckStrategies.NackWithRequeue;
}
public AckStrategy HandleConsumerCancelled(ConsumerExecutionContext context)
{
return AckStrategies.NackWithRequeue;
}
}
[TestMethod]
public void test()
{
var hostName = _configuration["RabbitMQ:HostName"];
var mqport = _configuration["RabbitMQ:Port"];
var userName = _configuration["RabbitMQ:UserName"];
var password = _configuration["RabbitMQ:Password"];
var connectionConfiguration = new ConnectionConfiguration
{
Hosts = new List<HostConfiguration>
{
new HostConfiguration
{
Host = hostName,
Port = Convert.ToUInt16(mqport)
}
},
Port = Convert.ToUInt16(mqport),
VirtualHost = "/",
UserName = userName,
Password = password
};
var _bus = RabbitHutch.CreateBus(connectionConfiguration , x=> {
x.Register<IConsumerErrorStrategy, AlwaysRequeueErrorStrategy>();
});
var exchange = _bus.Advanced.ExchangeDeclare("ExchangeNAME_test", ExchangeType.Topic);
var nickNameQu = _bus.Advanced.QueueDeclare("queuename2222");
int count = 0;
_bus.Advanced.Bind(exchange, nickNameQu, "RouterKey1");
_bus.Advanced.Consume(nickNameQu, (data, properties, info) =>
{
count++;
if (count < 2)
throw new Exception("my error");
var msg = Encoding.UTF8.GetString(data);
});
Task.Run(() => {
_bus.PublishAsync(new UpdateAvaterMessage() { Avater = "abcc22" }, "RouterKey1");
});
Thread.Sleep(100000);
}
原理是重写IConsumerErrorStrategy
(如果不是使用EasyNetQ,传统的RabbitMQ库是用手动ack实现)
另外,如果消息处理过程中,服务器死机,这种情况消息是会重发的,不需要担心
文章介绍了如何在EasyNetQ中使用自定义的AlwaysRequeueErrorStrategy处理消息处理过程中的异常,确保即使出现异常,RabbitMQ也能重新推送消息。测试方法展示了如何注册并应用这个策略,以及其与传统RabbitMQ库手动ack机制的区别。
在处理消息时,如果抛出异常,继续不断发送到订阅队列,不断处理(也就是不自动确认消息已到达)&spm=1001.2101.3001.5002&articleId=134923748&d=1&t=3&u=e095c5dbb39241b9b5024580e336e685)
6936

被折叠的 条评论
为什么被折叠?



