use*_*060 3 c# polly retry-logic
这2个重试策略表明相同吗?
Policy
.Handle<SomeExceptionType>()
.WaitAndRetry(
new[]
{
TimeSpan.FromMinutes(1),
TimeSpan.FromMinutes(1),
TimeSpan.FromMinutes(1)
});
Run Code Online (Sandbox Code Playgroud)
Policy
.Handle<SomeExceptionType>()
.WaitAndRetry(
3,
retryAttempt => TimeSpan.FromMinutes(1)
);
Run Code Online (Sandbox Code Playgroud)
是的,他们也这样做。
两个代码都定义了一个策略,该策略最多执行 4 次相同的操作:初始尝试 + 三次额外尝试。
两种重载之间的主要区别如下:
在您的特定示例中,您的第二个选择可以这样定义:
Policy
.Handle<SomeExceptionType>()
.WaitAndRetry(
3,
_ => TimeSpan.FromMinutes(1)
);
Run Code Online (Sandbox Code Playgroud)
使用丢弃运算符,您明确声明您没有在 中使用该参数sleepDurationProvider来计算新的延迟。
为了清楚起见,我在这篇文章中使用了可互换的penalty、delay和sleep术语。
更新#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);
}
);
Run Code Online (Sandbox Code Playgroud)
如果您使用断路器来避免下游系统在自我修复时发生洪水,您可以让您的重试意识到这一点。
By default all policies are independent and they are unaware of each other. If you issue a retry attempt while the CB is open then you will receive a BrokenCircuitException (so it short-cuts the execution). But you can dynamically calculate the delay based on the CB's state so you can skip these unnecessary retries.
The Circuit Breaker definition
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; });
Run Code Online (Sandbox Code Playgroud)
The retry definition
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);
});
Run Code Online (Sandbox Code Playgroud)
This advanced use case is described in detail here.