circuit-breaker - Polly 断路器/重试以在网络中断后自动重新启动查询
问题描述
我正在.NET 框架 4.5.2 中通过 Polly 实现断路器和重试模式。
我想看看我的理解是否正确。
问题一:如果网络中断,并且断路器已经达到了exceptionsAllowedBeforeBreaking数,进入open状态并等待durationOfBreak期间,电路会为新的请求打开,但是已经发送的会抛出异常?
问题 2:如果期望的行为是重试那些有异常的请求,而不是断路器抛出异常,那么除了断路器策略之外,还需要实施重试策略。我对此的理解是,问题 1 中的行为会发生,然后会尝试重试。
A. 如果网络中断或服务关闭,并且期望的行为是在网络恢复或服务再次启动时重试请求,则需要执行 RetryForever。有没有更好的方法来做到这一点?实际上会有很多阻塞,对吗?
在代码方面,我的策略目前定义为:
const int maxRetryAttempts = 3;
const int exceptionsAllowedBeforeBreaking = 2;
const int pauseBetweenFailures = 2;
readonly Policy retryPolicy = Policy
.Handle<Exception>()
.RetryAsync(maxRetryAttempts, (exception, retryCount) => System.Diagnostics.Debug.WriteLine($"Retry {retryCount}"));
readonly Policy circuitBreakerPolicy = Policy
.Handle<Exception>()
.CircuitBreakerAsync(exceptionsAllowedBeforeBreaking: exceptionsAllowedBeforeBreaking,
durationOfBreak: TimeSpan.FromSeconds(pauseBetweenFailures),
onBreak: (e, span) => System.Diagnostics.Debug.WriteLine("Breaking circuit for " + span.TotalMilliseconds + "ms due to " + e.Message),
onReset: () => System.Diagnostics.Debug.WriteLine("Trial call succeeded: circuit closing again."),
onHalfOpen: () => System.Diagnostics.Debug.WriteLine("Circuit break time elapsed. Circuit now half open: permitting a trial call."));
我的调用代码是这样完成的:
var response = await retryPolicy.WrapAsync(circuitBreakerPolicy).ExecuteAsync(() => this.client.SendAsync<TData, JObject>(message, cancel, jsonSerializer));
我观察到,如果我在断路器上运行所有重试所需的时间之后断开网络连接,则 CancellationToken 将设置为取消,并且所有请求此时都失败。如果在此之前网络已恢复,则重试请求。
解决方案
问题1:如果网络中断并且断路器已经达到exceptionsAllowedBeforeBreaking数量,进入打开状态并等待durationOfBreak期间,电路将为新请求打开......
在 durationOfBreak 过去之后,电路将转换到 Half-Open 状态,在此期间允许进行一次试调用(在当前实现中)。
...但是那些已经发送的会抛出异常吗?
在 Open 状态期间发出的调用将抛出BrokenCircuitException
.
问题 2:如果期望的行为是重试那些有异常的请求,而不是断路器抛出异常,那么除了断路器策略之外,还需要实施重试策略。我对此的理解是,问题 1 中的行为会发生,然后会尝试重试。
正确的。断路器仍然会抛出它BrokenCircuitException
(没有“替代”来阻止断路器这样做)。但是,如果包装重试策略处理了该异常,则不BrokenCircuitException
会将其传播回调用代码。可以在Polly-Samples或这个 dotnetfiddle中找到可运行的示例。
A. 如果网络中断或服务关闭,并且期望的行为是在网络恢复或服务再次启动时重试请求,则需要执行 RetryForever。实际上会有很多阻塞,对吗?
Polly 策略仅管理该执行路径上发生的事情,不知道是否存在类似的并行执行。所以是的,如果有一个RetryForever
并且如果您期望RetryForever
在连接丢失时循环大量调用,那么在保持模式中存在许多操作导致内存/资源膨胀的风险。要知道这是否是您的应用程序/架构的一个重要问题,您需要在代表性环境中进行试验。
有没有更好的方法来做到这一点?
您可以限制重试次数并将失败的发送捕获到某种队列中。连接恢复后,您可以重新发送故障队列中的项目。
推荐阅读
- c# - 如何使用 LINQ/Lambda 来缩短我的 C# 代码段?
- r - 如果不使用 bsButton(),shinyBS Popover 将无法正常工作
- python - Pyspark:仅读取特定日期的 ORC 数据
- c# - 如何动态生成ics文件?
- python-3.x - 将python字典中的一位数转换为两位数
- python - 将现有的相关字段迁移到 Django 中的另一个模型
- regex - 正则表达式和 Grafana:排除和字符串切割
- c# - 多对多 CRUD 操作 ASP.Net Core
- angularjs-scope - 如何设置 AngularJS 组件的作用域
- xml - URL 重写语法问题 R:0, R:1, R:2