EasyNetQ(RabbitMQ)在处理消息时,如果抛出异常,继续不断发送到订阅队列,不断处理(也就是不自动确认消息已到达)

默认情况下,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实现)

另外,如果消息处理过程中,服务器死机,这种情况消息是会重发的,不需要担心

posted @ 2021-04-20 16:43  IWing  阅读(302)  评论(0编辑  收藏  举报