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

如何用Polly实现首次10秒、后续5秒重试且总时长3分钟的逻辑?

解决Polly实现SqlConnection差异化延迟重试及总时长限制问题

核心问题分析

  1. 异常被内部拦截:你的reTryDB方法内部捕获了Exception但未重新抛出,导致Polly无法感知异常,重试逻辑永远不会触发。
  2. 策略拆分与组合错误:拆分两个重试策略并通过Wrap组合的方式不符合需求,且Wrap顺序错误——Timeout策略应作为外层控制总时长。
  3. Handle条件冗余:retryFirstTime中包含了DivideByZeroException,与SqlConnection重试需求无关,应剔除。

修正后的实现方案

步骤1:修复业务方法,确保异常能被Polly捕获

修改reTryDB方法,捕获异常后重新抛出,让Polly感知到错误:

public static void reTryDB(SqlConnection conn)
{
    Console.WriteLine($"Open Sql con at {DateTime.Now.ToString("hh.mm.ss.ffffff")}");

    try
    {
        conn.Open(); 

        string selectCommand = "SELECT TOP 1 * FROM [dbo].[TAbleA]";
        using var command = new SqlCommand(selectCommand, conn);
        
        using SqlDataReader reader = command.ExecuteReader();
        while (reader.Read())
        {
            Console.WriteLine(String.Format("{0}", reader[0]));
        }

        conn.Close();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Encountered error: {ex.ToString()}");
        throw; // 必须重新抛出,Polly才能触发重试
    }
}

步骤2:定义单一重试策略实现差异化延迟

通过WaitAndRetryForever的sleepDurationProvider参数,根据重试次数设置不同延迟:

// 首次重试延迟10秒,后续所有重试延迟5秒
Policy retryPolicy = Policy
    .Handle<SqlException>() // 仅针对SqlException触发重试
    .Or<TimeoutException>() // 可选:如需处理超时异常可保留
    .WaitAndRetryForever(
        sleepDurationProvider: retryAttempt => 
            retryAttempt == 1 ? TimeSpan.FromSeconds(10) : TimeSpan.FromSeconds(5),
        onRetry: (exception, retryDelay, retryCount, context) =>
        {
            Console.WriteLine($"Retry attempt {retryCount} - waiting {retryDelay.TotalSeconds}s before next try at {DateTime.Now.ToString("hh.mm.ss.ffffff")}");
        }
    );

步骤3:定义总时长超时策略

设置3分钟的总超时,控制整个重试流程的最长时间:

// 总重试时长不超过3分钟
Policy timeoutPolicy = Policy.Timeout(
    TimeSpan.FromMinutes(3), 
    TimeoutStrategy.Pessimistic, // 同步场景推荐使用Pessimistic策略
    (context, timespan, task) =>
    {
        Console.WriteLine($"Total retry duration exceeded {timespan.TotalMinutes} minutes, stopping retries.");
    }
);

步骤4:正确组合策略

将Timeout策略作为外层,重试策略作为内层,确保总时长限制生效:

Policy combinedPolicy = Policy.Wrap(timeoutPolicy, retryPolicy);

步骤5:使用组合策略

combinedPolicy.Execute(() => reTryDB(conn));

关键说明

  • 重试次数计数:WaitAndRetryForever中的retryAttempt从1开始计数,第一次重试对应retryAttempt=1,以此类推。
  • 策略组合逻辑:Policy.Wrap(外层策略, 内层策略),外层的Timeout策略会包裹整个重试流程,确保总时长不超限。
  • 异常传递要求:业务方法必须将异常抛出,Polly才能触发重试逻辑,内部捕获后不抛出会导致重试完全失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 10:49:51