使用 RabbitMQ 的 Masstransit,消息在正确处理消费者后传递两次

Masstransit with RabbitMQ, message delivered twice after a correct handling of the consumer

我的消费者有这种 MassTransit (RabbitMQ) 配置。重试策略是在最多 5 个间隔超时时重新发送消息。

ep.ConfigureConsumer<T>(ctx,
    c => {
        c.UseMessageRetry(r =>
        {
            r.Interval(5, TimeSpan.FromMinutes(30));
            r.Handle<Exception>(m => m.GetFullMessage().Contains("Timeout"));
            r.Ignore(typeof(ApplicationException)); 
            });
        c.UseConcurrentMessageLimit(1);
    });

    ep.Bind(massTransitSettings.ExchangeName, y =>
    {
        y.Durable = true;
        y.AutoDelete = false;
        y.ExchangeType = massTransitSettings.ExchangeType;
        y.RoutingKey = massTransitSettings.RoutingKey;                            
    });
});

一切正常,除非有时同一消息连续两次超时;

Here a part of log file for message id: fa300000-56b5-0050-e012-08d9f39bc934
19/02/2022 12:34:28.699 - PAYMENT INCOMING Message -> Sql timeout, retry in 30 min
19/02/2022 13:04:28.572 - PAYMENT INCOMING Message -> 2th Sql timeout, retry in 30 min
19/02/2022 13:34:59.722 - PAYMENT INCOMING Message -> Process ok    
19/02/2022 13:35:13.983 - PAYMENT HANDLED  Message -> Message handled (74 secs)
19/02/2022 13:35:31.606 - PAYMENT INCOMING Message -> This should not incoming, causing an Application Exception (message in _error queue)

我哪里错了?

您不能在那么长的时间间隔内使用消息重试,因为 RabbitMQ 的默认使用者超时为 30 分钟。根据文档:

MassTransit retry filters execute in memory and maintain a lock on the message. As such, they should only be used to handle short, transient error conditions. Setting a retry interval of an hour would fall into the category of bad things. To retry messages after longer waits, look at the next section on redelivering messages.

要获得更长的重试间隔,请使用 message redelivery(有时称为 second-level 重试)。如果您使用的是 RabbitMQ,built-in 延迟重新交付需要 delayed-exchange plug-in。或者您可以使用外部消息调度程序。