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

如何为带自定义请求头的异步POST请求应用Polly重试策略?

解决方案:每次重试生成新HttpRequestMessage

你遇到的核心问题是预创建的HttpRequestMessage只能被发送一次,Polly重试时重复使用同一个实例就会抛出“请求已发送,无法复用”的异常。要同时满足重试和动态修改请求头的需求,最直接的解决方式是让Polly每次重试时都创建新的请求实例。

直接修改执行委托

把请求的创建逻辑放到ExecuteAsync的委托中,这样每次重试都会执行这段代码,生成全新的HttpRequestMessage:

using HttpResponseMessage response = await RetryPolicy.ExecuteAsync(() => 
{
    // 每次重试都会重新创建请求,动态设置请求头
    HttpRequestMessage request = new(HttpMethod.Put, new Uri(url));
    request.Content = new StringContent(GetJson(code), Encoding.UTF8, "text/json");
    request.Headers.Add("tenant", GetId(code));
    
    return Client.SendAsync(request);
});

封装请求构建逻辑(优化代码整洁度)

如果多个地方需要类似逻辑,可以把请求创建抽成单独的方法,避免重复代码:

// 封装请求构建逻辑
private HttpRequestMessage CreateTenantPutRequest(string url, string code)
{
    var request = new HttpRequestMessage(HttpMethod.Put, new Uri(url));
    request.Content = new StringContent(GetJson(code), Encoding.UTF8, "text/json");
    request.Headers.Add("tenant", GetId(code));
    return request;
}

// 使用Polly重试时调用该方法
using HttpResponseMessage response = await RetryPolicy.ExecuteAsync(() => 
    Client.SendAsync(CreateTenantPutRequest(url, code))
);

为什么这个方案可行?

  • 避免了请求实例复用:每次重试都会生成全新的HttpRequestMessage,不存在“已发送”的状态问题。
  • 满足动态请求头需求:GetId(code)每次都会重新执行,确保请求头是最新的(如果GetId的返回值可能变化的话)。

对之前尝试方法的补充说明

  • 特定方法加请求头:确实没有直接的重载,但可以通过自定义DelegatingHandler实现全局请求头注入,但如果是每次调用都需要动态变化的头,还是上述方法更直接。
  • 修改客户端默认请求头:HttpClient的默认头是线程不安全的,异步场景下容易出现竞态条件,不推荐用于动态变化的请求头。
  • 每个租户一个客户端:会导致大量HttpClient实例,违背了HttpClient应复用的最佳实践,浪费资源。
  • 在重试处理程序中创建请求:不需要这么做,Polly的ExecuteAsync委托本身就是每次重试都会执行的逻辑,把请求创建放在这里更符合设计逻辑。

内容的提问来源于stack exchange,提问作者Konrad Viltersten

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:15:42