繁体   English   中英

使用 Polly 重试

[英]retry using Polly

这 2 个重试策略是否表示相同?

Policy
    .Handle<SomeExceptionType>()
    .WaitAndRetry(
        new[]
        {
            TimeSpan.FromMinutes(1),
            TimeSpan.FromMinutes(1),
            TimeSpan.FromMinutes(1)
        });
Policy
    .Handle<SomeExceptionType>()
    .WaitAndRetry(
        3,
        retryAttempt => TimeSpan.FromMinutes(1)
    );

是的,他们也这样做。

两个代码都定义了一个策略,该策略最多执行 4 次相同的操作:初始尝试 + 3 次额外尝试。

两种重载的主要区别如下:

  • 前者以静态方式定义惩罚
    • 它预先定义了不同尝试之间的延迟
  • 后者以动态的方式定义惩罚
    • 它可以根据即将发生的重试来计算延迟

在您的特定示例中,您的第二种选择可以这样定义:

Policy
    .Handle<SomeExceptionType>()
    .WaitAndRetry(
        3,
        _ => TimeSpan.FromMinutes(1)
    );

使用丢弃运算符,您明确声明您没有在sleepDurationProvider中使用该参数来计算新的延迟。


为了清楚起见,我在这篇文章中使用了可互换的惩罚延迟睡眠术语。


更新#1

以下是您可以利用动态惩罚计算的两个示例。

指数退避+抖动

与其在每次尝试之间等待相同的时间,不如使用越来越大的延迟来为下游系统提供自我修复空间。 因此,例如:2、4、8 ...

抖动只是一个小的随机数,以避免所有客户端同时尝试发送重试尝试。 因此它会及时分散/分散客户端的重试尝试。

const int maxDelayInMilliseconds = 32 * 1000;
var jitterer = new Random();
Policy
  .Handle<HttpRequestException>()
  .WaitAndRetryForever(
      retryAttempt =>
      {
          var calculatedDelayInMilliseconds = Math.Pow(2, retryAttempt) * 1000;
          var jitterInMilliseconds = jitterer.Next(0, 1000);

          var actualDelay = Math.Min(calculatedDelayInMilliseconds + jitterInMilliseconds, maxDelayInMilliseconds);
          return TimeSpan.FromMilliseconds(actualDelay);
      }
  );

断路器感知重试

如果您使用断路器来避免在下游系统自我修复时淹没下游系统,您可以让您的重试意识到这一点。

默认情况下,所有策略都是独立的,并且它们彼此不知道。 如果您在 CB 打开时发出重试尝试,那么您将收到BrokenCircuitException (因此它会缩短执行)。 但是您可以根据 CB 的状态动态计算延迟,这样您就可以跳过这些不必要的重试。

断路器定义

Policy<HttpResponseMessage>
    .HandleResult(res => res.StatusCode == HttpStatusCode.InternalServerError)
    .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2),
       onBreak: (dr, ts, ctx) => { ctx[SleepDurationKey] = ts; },
       onReset: (ctx) => { ctx[SleepDurationKey] = null; });

重试定义

Policy<HttpResponseMessage>
    .HandleResult(res => res.StatusCode == HttpStatusCode.InternalServerError)
    .Or<BrokenCircuitException>()
    .WaitAndRetryAsync(4,
        sleepDurationProvider: (c, ctx) =>
        {
            if (ctx.ContainsKey(SleepDurationKey))
                return (TimeSpan)ctx[SleepDurationKey];
            return TimeSpan.FromMilliseconds(200);
        });

此处详细描述了此高级用例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM