Polly无法在指定异常触发时重试Http请求问题排查
Polly重试策略未生效,直接抛出连接拒绝异常
问题代码
服务定义
var host = new HostBuilder().ConfigureServices(services => { services .AddHttpClient<Downloader>() .AddPolicyHandler((services, request) => HttpPolicyExtensions .HandleTransientHttpError() .Or<SocketException>() .Or<HttpRequestException>() .WaitAndRetryAsync( new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10) }, onRetry: (outcome, timespan, retryAttempt, context) => { Console.WriteLine($"Delaying {timespan}, retrying {retryAttempt}."); })); services.AddTransient<Downloader>(); }).Build();
Downloader实现
class Downloader { private HttpClient _client; public Downloader(IHttpClientFactory factory) { _client = factory.CreateClient(); } public Download() { await _client.GetAsync(new Uri("localhost:8800")); // 无应用监听的端口 } }
现象
配置上述代码后,预期触发3次请求尝试(初始1次+2次重试)并打印重试日志,但实际无任何重试日志,直接抛出未处理异常:
未处理异常: System.Net.Http.HttpRequestException: 由于目标计算机积极拒绝,无法连接。(127.0.0.1:8800)
---> System.Net.Sockets.SocketException (10061): 由于目标计算机积极拒绝,无法连接。
解决方法
1. 修正HttpClient注入方式
AddHttpClient<Downloader>()已经为Downloader配置了绑定Polly策略的HttpClient,无需通过IHttpClientFactory手动创建新实例,直接注入HttpClient即可:
class Downloader { private readonly HttpClient _client; // 直接注入配置好策略的HttpClient public Downloader(HttpClient client) { _client = client; } public async Task Download() { await _client.GetAsync(new Uri("http://localhost:8800")); } }
2. 修复Uri格式
原代码中localhost:8800缺少协议头,会被解析为相对Uri,导致异常处理逻辑失效,添加http://确保是绝对路径。
3. 修正方法签名
原Download方法缺少async修饰符和Task返回值,会导致编译错误且无法触发异步重试策略,必须修正为异步方法。
4. 移除重复服务注册
AddHttpClient<Downloader>()已经自动将Downloader注册为Transient服务,无需再调用services.AddTransient<Downloader>(),移除该行避免冲突。
修正后的服务定义:
var host = new HostBuilder().ConfigureServices(services => { services .AddHttpClient<Downloader>() .AddPolicyHandler((services, request) => HttpPolicyExtensions .HandleTransientHttpError() .Or<SocketException>() .Or<HttpRequestException>() .WaitAndRetryAsync( new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10) }, onRetry: (outcome, timespan, retryAttempt, context) => { Console.WriteLine($"Delaying {timespan}, retrying {retryAttempt}."); })); }).Build();
完成上述修改后,Polly重试策略会正常触发,控制台会打印两次重试日志,总共执行3次请求尝试。
内容的提问来源于stack exchange,提问作者Dr. Strangelove
相关产品推荐
相关产品推荐

