3

当由于连接池耗尽而收到超时异常时,我们正在尝试为我们的数据库逻辑实施重试策略。当我们在短时间内出现异常大的活动高峰时,就会发生这种情况。我们增加了最大池大小来尝试避免这种情况,但我们也希望将重试逻辑作为备份计划。

连接池的文档指出:

启用连接池后,如果发生超时错误或其他登录错误,将引发异常,随后的连接尝试将在接下来的五秒内失败,即“阻塞期”。如果应用程序在阻塞期内尝试连接,将再次抛出第一个异常。阻塞期结束后的后续故障将导致新的阻塞期是前一个阻塞期的两倍,最长为一分钟。

Polly 似乎很适合解决这个问题,它通过策略包装结合了 Fallback、WaitAndRetry 和 Circuit Breaker 策略。这里有一张很好的照片

理想情况下,我希望能够为断路器指定指数 durationOfBreak 以匹配上述加倍周期。我在网上没有看到任何关于这如何可能的例子,所以也许这是不可能的?

这里所需的配置方法是什么?是否指定一个具有 5 秒 durationOfBreak 的断路器,然后对 5、10、20、40 和 60 秒的 WaitAndRetry 组件使用指数重试?如果连接刚刚变得可用并且您的旧操作刚刚开始等待 40 秒,而新操作将立即起作用,这似乎很不幸。

另一种可能性是有一个 5 秒的 durationOfBreak ,然后让 WaitAndRetry 组件使用一个非常小的等待并进行大量重试,即使我们知道如果这些重试中的许多重试在文档状态之前出现,它们也会失败。

感谢您的反馈!

4

1 回答 1

3

Polly 不提供具有不同(例如指数)断路持续时间的断路器。

以下内容乍一看可能违反直觉,但是:听起来这种情况不需要具有指数回退的断路器,因为所描述的 ADO.NET 连接池算法已经有效地提供了这一点。

推理:熔断器的目的是停止将调用传递给不太可能处理它们的下游系统,以便: (a) 调用者快速失败;(b) 保护底层系统免受过度负载。听起来好像 ADO.NET 的算法已经实现了这两个目标。

类似地,指数回退重试策略的目标是防止重试本身“增加”负载(在底层系统上创建自我诱导的 DDOS 攻击......更多请求进入并且现有请求也在重试)。同样,听起来 ADO.NET 的 force-you-to-back-off 算法正在强制执行其自己的指数回退以保护底层数据库,因此 (*) 将您自己的 Polly 指数回退分层可能没有任何好处-最重要的是。

在 ADO.NET 提供自己的防御的基础上,我很想做一些简单的事情,比如使用固定重试间隔为 5 秒或 5-plus-tiny-shim 秒的重试策略。(无论“封锁期”是什么有效的,似乎都是 5 秒的倍数。)

此建议基于此 ADO.NET 连接池管理(就此阻塞期而言)所有发生在调用方的假设;即,调用应用程序中嵌入的 ADO.NET 代码决定其连接池已被充分利用,并在阻塞期间拒绝进一步的连接尝试,而无需将网络调用通过底层 SQL 服务器进行检查。如果该假设不正确,那么上面的建议 (*) 可能是错误的,您最好使用指数退避重试策略来避免连接重试尝试使数据库服务器过载。


警告:我没有直接使用这个特定的 ADO.NET 限制。那些有可能有更好的建议。那些更了解内部 ADO.NET 架构的人可能更清楚每五秒(如我所建议的那样)不断尝试可能会被拒绝是多么“昂贵”。


附录:该讨论还忽略了调用者中任何导致线程/CPU 饥饿或类似情况的高并行需求维度。如果这是一个问题,请考虑在某个已知的可容忍限度内进行主动减载。

于 2019-04-17T22:38:34.043 回答