首页 > 解决方案 > 使用 Polly 重试处理较长时间间隔的 HTTP 请求错误是否安全

问题描述

我试图为我的应用程序实现我自己的 WebHooks 版本。当用户注册他们的 URL 挂钩时(假设它的 URL 错误或不会用 2XX 代码响应),我想在自定义指数间隔内重试多达五次,例如 5 分钟、30 分钟、2 小时、4 小时和 16 小时. 我已经使用 .NET Polly 库实现了这一点。

我的问题是,

1) 在最坏的情况下,第 5 次重试延长 16 小时是否安全?

2)它是线程安全的(Polly 说,只要我的代码是线程安全的,它就是线程安全的),但我担心的是 16 小时长的间隔。

3) 假设 10 个请求失败,并且所有请求都在各自的时间间隔内重试。那么,越来越多的请求在一段时间后失败,我的服务器线程池是否会变满并且无法接受任何新请求?

4) 由于间隔时间长,真的值得使用 Polly 之类的库还是更好地使用 CRON 作业调度程序?

IHttpClientFactory我的实现细节与 Polly 的官方示例(链接)非常相似或相同。

谢谢你的建议。

标签: c#multithreadingasp.net-corethread-safetypolly

解决方案


我强烈建议您深入研究 Polly 源代码,它相对容易阅读。

例如,如果您从WaitAndRetryAsync功能开始,您将很快到达AsyncRetryEngine. 这包含重试实现,这就是为什么它是唯一的方法调用ImplementationAsync。如果我们跳到与等待相关的部分,那么您将在那里找到以下代码:

if (waitDuration > TimeSpan.Zero)
{
      await SystemClock.SleepAsync(waitDuration, cancellationToken).ConfigureAwait(continueOnCapturedContext);
}

如果你看一下,SystemClock你会发现SleepSleepAsync字段(方法)定义:

public static Func<TimeSpan, CancellationToken, Task> SleepAsync = 
   new Func<TimeSpan, CancellationToken, Task>(Task.Delay);

SystemClock.Sleep = (Action<TimeSpan, CancellationToken>) ((timeSpan, cancellationToken) =>
  {
    if (!cancellationToken.WaitHandle.WaitOne(timeSpan))
      return;
    cancellationToken.ThrowIfCancellationRequested();
  });

如您所见,如果您调用 ,WaitAndRetryAsync那么您的策略将调用Task.Delay,这是非阻塞的。如果您调用 the ,WaitAndRetry那么您的策略将调用WaitHandle's WaitOne,这是阻塞的。

因此,如果您在很长一段时间内使用 WaitAndRetry ,那么这将阻塞线程(除非它由于某种原因被终止)。在 WaitAndRetryAsync 的情况下,线程池将在延迟完成后收到有关完成的通知。


但我仍然建议使用 cron 作业来解决这类问题。


推荐阅读