Polly的WaitAndRetryAsync如何实现RetryCompleted/OnRetryComplete回调功能
问题1:重试次数耗尽后抛出异常的实现
Polly的重试策略在耗尽所有配置的重试次数后,会直接透传最后一次执行的异常或结果,你可以通过两种方式实现抛出异常的需求:
- 沿用现有逻辑:你在执行委托中调用了
EnsureSuccessStatusCode(),该方法会自动将非成功状态码的响应转换为HttpRequestException抛出,你的策略已经配置了捕获该异常重试,重试耗尽后最后一次的异常会直接向外抛出,被外层catch块捕获后转抛自定义异常即可。 - 策略层统一处理:通过Fallback策略在重试耗尽时统一抛出异常,无需在业务代码中重复处理状态码判断。
问题2:重试耗尽后的自定义回调实现
Polly没有名为OnRetryComplete的内置配置项,但可以通过Fallback策略与PolicyWrap组合实现该需求,所有重试次数耗尽后会自动触发Fallback的自定义逻辑,支持告警推送、日志记录等自定义操作。
完整改造代码示例
策略定义部分
// 重试策略:重试2次,每次间隔200ms var retryPolicy = Policy .Handle<Exception>() .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode) .WaitAndRetryAsync(2, _ => TimeSpan.FromMilliseconds(200), // 可选配置:每次重试触发的回调,可用于记录重试日志 onRetryAsync: (outcome, timespan, retryAttempt, context) => { logger.LogInformation("第 {Attempt} 次重试,间隔 {Delay}ms", retryAttempt, timespan.TotalMilliseconds); return Task.CompletedTask; }); // Fallback策略:所有重试耗尽后触发,对应你需要的OnRetryComplete效果 var fallbackPolicy = Policy<HttpResponseMessage> .Handle<Exception>() .OrResult(r => !r.IsSuccessStatusCode) .FallbackAsync( fallbackAction: (result, context, cancellationToken) => { // 此处填写自定义逻辑:推送告警、记录错误日志等 logger.LogError("所有重试已耗尽,仍未获取成功响应,最后一次状态:{Status}", result.Exception != null ? "请求异常" : result.Result.StatusCode.ToString()); // 直接抛出自定义异常 throw new CustomException("多次重试后请求仍失败"); }); // 组合策略:Fallback外层包裹重试策略,先执行重试,重试耗尽后进入Fallback逻辑 var policyWrap = Policy.WrapAsync(fallbackPolicy, retryPolicy);
业务执行部分
try { var responseMessage = await policyWrap.ExecuteAsync(async () => { string requestJson = JsonSerializer.Serialize(eligRequest, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); using var content = new StringContent(requestJson, Encoding.UTF8, "application/json"); return await httpClient.PostAsync("test/api/ate", content); }); return responseMessage; } catch (CustomException ex) { // 外层可按需做额外处理后抛出 logger.LogError(ex, "请求最终执行失败"); throw; }
补充说明
WaitAndRetryAsync(2, ...)配置代表额外重试2次,加上第一次原始请求,总共会发起3次请求,如果你需要总共2次请求,将重试次数改为1即可。- 如果你不想引入Fallback策略,也可以直接在外层catch块中写入自定义逻辑,重试耗尽后抛出的异常会直接进入catch块,效果等价于重试完成回调。
内容的提问来源于stack exchange,提问作者Sheriff
相关产品推荐
相关产品推荐

