Polly HandleTransientHttpError未捕获HttpRequestException原因及解决方案咨询
问题根因
首先明确Polly通过AddPolicyHandler挂载到HttpClient的重试策略,仅作用于HttpClient消息管道的执行周期内,也就是仅覆盖SendAsync方法从调用到返回HttpResponseMessage的阶段:
- ASP.NET Core HttpClient默认使用
HttpCompletionOption.ResponseHeadersRead作为参数执行请求,也就是说只要成功接收完响应头(你日志里拿到200状态码就是这个阶段完成),就会立刻返回HttpResponseMessage对象,此时响应体还没有开始读取 - 你遇到的
HttpRequestException是后续执行response.Content.ReadAsStringAsync()读取响应体时,底层TCP连接读取chunked编码的响应内容出错抛出的,这个执行阶段已经脱离了Polly策略的覆盖范围,所以现有重试策略不会触发
解决方案
你可以根据业务场景选择以下任意一种方案处理:
方案1:调整请求完成选项(推荐,改动最小)
将SendAsync的调用参数调整为HttpCompletionOption.ResponseContentRead,让HttpClient在SendAsync阶段就完成完整响应体的读取,整个过程的异常都会被管道内的Polly策略捕获:
// 调整前 // using (HttpResponseMessage response = await _httpClient.SendAsync(request)) // 调整后 using (HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead))
改完之后你现有的重试策略无需任何调整,HandleTransientHttpError()本身就可以处理这个阶段抛出的HttpRequestException,会正常触发重试逻辑。
方案2:外层包装业务级重试策略
如果你有大响应体场景不能全量缓冲响应内容,就需要在包含SendAsync+读取响应体的完整业务逻辑外层包装重试策略:
- 策略需要同时处理
HttpResponseMessage异常状态码、HttpRequestException以及你自己封装的ActivityException - 注意每次重试都要重新构造
HttpRequestMessage对象,不能复用之前已经被处理过的请求实例
补充说明
你观察到的该异常是瞬态错误完全符合预期,属于服务器端响应发送过程中连接中断的场景,重试即可恢复,不需要额外做其他兼容处理。
内容的提问来源于stack exchange,提问作者SeanOB
相关产品推荐
相关产品推荐

