瘴锲如 发表于 2025-6-14 03:02:46

指数退避: 一种常用于网络请求重试的策略

"指数退避"(Exponential Backoff)是一种常用于网络请求重试的策略。其核心思想是:每当操作失败并需要重试时,不是立即重试,而是等待一段时间再重试,并且每次重试之间的等待时间呈指数级增长(通常是成倍增加)。

实现指数退避的逻辑:
await Task.Delay(delayMilliseconds * attempt);
这里,每重试一次,等待时间就会增加(第1次等待1倍,第2次2倍,第3次3倍……)。这样做的好处是可以减轻服务器压力,避免因频繁重试导致网络拥堵或服务雪崩。
常见的指数退避公式为:
等待时间 = 基础延迟 * 2^重试次数
上面的实现是线性递增(delayMilliseconds * attempt),如果要严格指数退避,可以改为:
await Task.Delay(delayMilliseconds * (int)Math.Pow(2, attempt));
总结:
指数退避就是每次重试等待的时间越来越长,常用于处理网络异常、请求超时等场景,提高系统的健壮性和容错能力。
C# 中实现指数退避的具体代码示例:
using System;
using System.Net.Http;
using System.Threading.Tasks;

public static class RetryHelper
{
    /// <summary>
    /// 使用指数退避策略重试异步操作
    /// </summary>
    /// <typeparam name="T">返回类型</typeparam>
    /// <param name="action">要执行的异步操作</param>
    /// <param name="maxRetries">最大重试次数</param>
    /// <param name="baseDelayMilliseconds">基础延迟(毫秒)</param>
    /// <returns>操作结果</returns>
    public static async Task<T?> RetryWithExponentialBackoffAsync<T>(
      Func<Task<T?>> action,
      int maxRetries = 5,
      int baseDelayMilliseconds = 500)
    {
      int attempt = 0;
      while (true)
      {
            try
            {
                return await action();
            }
            catch (Exception ex) when (attempt < maxRetries)
            {
                attempt++;
                int delay = baseDelayMilliseconds * (int)Math.Pow(2, attempt - 1);
                Console.WriteLine($"第{attempt}次重试,等待{delay}ms,异常信息: {ex.Message}");
                await Task.Delay(delay);
            }
      }
    }
}用法示例:
// 假设有一个可能抛出异常的异步方法
async Task<string?> GetDataAsync()
{
    // 这里模拟网络请求
    throw new HttpRequestException("网络错误");
}

// 调用带指数退避的重试方法
var result = await RetryHelper.RetryWithExponentialBackoffAsync(GetDataAsync);说明:

[*]每次重试等待时间为 baseDelayMilliseconds * 2^(attempt-1),即 500ms, 1000ms, 2000ms, 4000ms, ...
[*]只要未超过最大重试次数,遇到异常就会指数级延迟后重试。
[*]你可以根据实际需求调整最大重试次数和基础延迟时间。
如需将你现有的 RetryAsync 方法改为严格的指数退避,只需将 await Task.Delay(delayMilliseconds * attempt); 替换为:
await Task.Delay(delayMilliseconds * (int)Math.Pow(2, attempt - 1));这样即可实现标准的指数退避。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 指数退避: 一种常用于网络请求重试的策略