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

基于重试次数调整超时时长:Polly实现方案咨询

实现Polly动态超时+重试的方案

刚好碰到过类似的需求,咱们可以通过Polly的策略组合+上下文传递重试次数来实现首次短超时、重试时递增超时的效果,直接上代码和解释:

核心思路

我们需要把Retry策略和Timeout策略结合起来:

  1. 用Retry策略捕获超时(或其他需要重试的异常),并在每次重试时把当前重试次数存入Polly的Context对象
  2. Timeout策略从Context中读取重试次数,动态计算对应的超时时长
  3. 把两个策略组合,让每次重试都使用对应的超时时间

完整代码示例

using Polly;
using Polly.Timeout;
using System.Net.Http;

// 定义超时时长的计算逻辑:首次请求短超时,重试时递增
TimeSpan CalculateTimeout(int retryCount)
{
    // 示例规则:首次500ms,每次重试加1000ms;也可以改成指数退避(比如500→1000→2000→4000)
    return retryCount == 0 
        ? TimeSpan.FromMilliseconds(500) 
        : TimeSpan.FromMilliseconds(500 + retryCount * 1000);
}

// 1. 创建Retry策略:捕获超时异常,重试时记录次数到Context
var retryPolicy = Policy
    .Handle<TimeoutRejectedException>() // 捕获Timeout策略抛出的超时异常
    .Or<HttpRequestException>() // 如果请求本身失败也需要重试,可以加上这个
    .Retry(3, (exception, retryCount, context) =>
    {
        // 把当前重试次数存入Context,供Timeout策略使用
        context["RetryCount"] = retryCount;
        Console.WriteLine($"触发第 {retryCount} 次重试,原因:{exception.Message}");
    });

// 2. 创建动态Timeout策略:从Context读取重试次数,计算超时
var timeoutPolicy = Policy.Timeout((context) =>
{
    // 首次请求时,Context里还没有RetryCount,默认用0(首次超时)
    if (context.TryGetValue("RetryCount", out var retryCountObj) && retryCountObj is int retryCount)
    {
        return CalculateTimeout(retryCount);
    }
    return CalculateTimeout(0);
});

// 3. 组合策略:Retry在外,Timeout在内,确保每次重试都应用对应超时
var combinedPolicy = Policy.Wrap(retryPolicy, timeoutPolicy);

// 4. 执行你的请求逻辑
try
{
    var result = await combinedPolicy.ExecuteAsync(async (context) =>
    {
        // 这里替换成你的实际请求代码,比如调用HttpClient
        using var client = new HttpClient();
        var response = await client.GetAsync("https://your-api-endpoint.com");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }, new Context()); // 传递Context用于存储重试次数

    Console.WriteLine("请求成功:" + result);
}
catch (TimeoutRejectedException)
{
    Console.WriteLine("所有重试均超时,请求失败");
}
catch (HttpRequestException)
{
    Console.WriteLine("请求失败,重试后仍未恢复");
}

关键细节说明

  • 重试次数对应关系:首次请求没有重试(retryCount=0),第一次重试对应retryCount=1,以此类推,刚好匹配我们的超时计算逻辑
  • 超时规则自定义:你可以随便修改CalculateTimeout方法的逻辑,比如改成指数退避(500 * Math.Pow(2, retryCount)),或者固定的阶梯时长,完全看你的需求
  • 异常范围控制:如果只需要在超时的时候重试,就只保留.Handle<TimeoutRejectedException>();如果其他请求异常(比如网络错误)也需要重试,就加上.Or<HttpRequestException>()等你需要的异常类型
  • 同步/异步兼容:如果是同步请求,把ExecuteAsync改成Execute即可,其他逻辑完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:33:34