You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 00:45:04