重试
重试时间
当消费者 ExecuteAsync
方法异常时,框架会进行重试,默认会重试三次,按照 2 作为指数设置重试时间间隔。
第一次失败后,立即重试,然后间隔 2 秒重试,第二次失败后,间隔 4 秒,接着分别是 8、16 秒。
Maomi.MQ.RabbitMQ 使用了 Polly 框架做重试策略管理器,默认通过 DefaultRetryPolicyFactory 服务生成重试间隔策略。
DefaultRetryPolicyFactory 代码示例如下:
/// <summary>
/// Default retry policy.<br />
/// 默认的策略提供器.
/// </summary>
public class DefaultRetryPolicyFactory : IRetryPolicyFactory
{
protected readonly int RetryCount = 3;
protected readonly int RetryBaseDelaySeconds = 2;
protected readonly ILogger<DefaultRetryPolicyFactory> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultRetryPolicyFactory"/> class.
/// </summary>
/// <param name="logger"></param>
public DefaultRetryPolicyFactory(ILogger<DefaultRetryPolicyFactory> logger)
{
_logger = logger;
RetryCount = 3;
RetryBaseDelaySeconds = 2;
}
/// <inheritdoc/>
public virtual Task<AsyncRetryPolicy> CreatePolicy(string queue, string id)
{
// Create a retry policy.
// 创建重试策略.
var retryPolicy = Policy
.Handle<Exception>()
.WaitAndRetryAsync(
retryCount: RetryCount,
sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(RetryBaseDelaySeconds, retryAttempt)),
onRetry: async (exception, timeSpan, retryCount, context) =>
{
_logger.LogDebug("Retry execution event,queue [{Queue}],retry count [{RetryCount}],timespan [{TimeSpan}]", queue, retryCount, timeSpan);
await FaildAsync(queue, exception, timeSpan, retryCount, context);
});
return Task.FromResult(retryPolicy);
}
public virtual Task FaildAsync(string queue, Exception ex, TimeSpan timeSpan, int retryCount, Context context)
{
return Task.CompletedTask;
}
}
你可以通过实现 IRetryPolicyFactory 接口,替换默认的重试策略服务服务。
services.AddSingleton<IRetryPolicyFactory, DefaultRetryPolicyFactory>();
持久化剩余重试次数
当消费者处理消息失败时,默认消费者会重试 3 次,如果已经重试了 2 次,此时程序重启,那么下一次消费该消息时,最后重试一次。
需要记忆重试次数,在程序重启时,能够按照剩余次数进行重试。
引入 Maomi.MQ.RedisRetry 包。
配置示例:
builder.Services.AddMaomiMQ((MqOptionsBuilder options) =>
{
options.WorkId = 1;
options.AutoQueueDeclare = true;
options.AppName = "myapp";
options.Rabbit = (ConnectionFactory options) =>
{
// ... ...
};
}, [typeof(Program).Assembly]);
builder.Services.AddMaomiMQRedisRetry((s) =>
{
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.3.248");
IDatabase db = redis.GetDatabase();
return db;
});
默认 key 只会保留 5 分钟。也就是说,如果五分钟之后程序才重新消费该消息,那么就会剩余重试次数就会重置。