【问题标题】:Is using a circuit breaker approach to handling http 429 responses too much of an overkill使用断路器方法来处理 http 429 响应太过分了
【发布时间】:2019-08-23 07:58:17
【问题描述】:

我有一个我调用的服务。让我们称之为LookupService。我的客户端应用程序中有以下代码行调用该服务

var resp= serviceClient.Lookup(payLoad);

现在LookupService 已由该服务的所有者配置为每个客户端不允许超过 5 个并发服务调用。除此之外,它们将返回 HTTP 429。

我正在考虑在调用Lookup 方法之前将这个调用注入到检查方法中。大意是:

ICircuitBreaker cb = CircuitBreakerFactory.GetInstance(); //return a retry instance
cb.Break();
var resp= serviceClient.Lookup(payLoad);

到目前为止,我只想在达到最大并发调用数或服务返回 http 代码 429 时暂停并重试。我将在每次调用 Lookup 方法之前注册到内部静态变量并取消注册服务返回时的调用。 但稍后,我将想要实现另一个类,它提供替代的操作路径或使用回退服务。我知道有一个重试模式,但我觉得注册每个呼叫并跟踪正在进行的呼叫以与服务允许的总允许呼叫进行比较,因为我已经知道提前会帮助我在我先发制人地打破电路知道它会失败。

关于这种模式的想法。可行,完美,矫枉过正?

【问题讨论】:

  • 让我知道我可以将这个问题发布到哪个板,如果这不是正确的板。
  • 如果当前出现调用过多的情况,或者您预见它会在不久的将来发生,那么断路器并不是矫枉过正。否则,如果您想添加它以防万一将来某个时候需要它,这可能是矫枉过正,尽管如果花时间添加它不是问题,那么无论如何添加它是一个很好的试验机会
  • 您实际上是如何进行 HTTP 消息传递的?如果可能,您可以访问到该服务器的所有连接都在使用的ServicePoint 或道德上等效的对象,并应用连接限制(例如,对于HttpClient,您可以手动构造HttpClientHandler 和设置其MaxConnectionsPerServer 属性)

标签: c# .net design-patterns polly circuit-breaker


【解决方案1】:

根据您提出的问题,我可以看到围绕不同弹性策略的一些混淆。让我试着把它们说清楚。

consumer-side (reactive) 和 producer-side (proactive) 模式/技术 /策略。前者通常对 fault 做出反应,而后者则试图防止错误/故障。

众所周知的消费者端模式:超时重试断路器
众所周知的生产者端模式:速率限制减载背压bulkhead

为了提供可靠的解决方案,仅在一侧应用模式通常是不够的。换句话说,只有智能客户端才能对服务器的回退请求做出反应。


据我了解,您希望限制来自同一台机器的并发请求。让我们一一检查生产者和消费者:

1) 生产者端
速率限制模式(也称为throttling)通常用于防止请求泛滥。您可以定义几对 durationthreshold 来描述给定机器的可接受负载:

  • 5 个请求/分钟
  • 100 个请求/小时
  • 1000 个请求/天

如果用户超过任何阈值,那么您可以施加某种惩罚。通常这是通过拒绝403 的请求来完成的。当持续时间到期时,计数器会重新设置为零,服务会再次接收来自客户端的请求。

有些实现使用429(请求太多)状态码代替403。这也是正确的,但它是两种模式的组合。 背压是另一种模式。这种技巧可以用来温和地告诉客户“我现在很忙,请稍后再来”。在这里,您可以通过指定 Retry-After 标头来定义客户端何时返回。这可以是绝对相对日期时间:

  • 绝对,例如:2020 年 4 月 29 日星期三 08:11:00 GMT
  • 相对,例如:120 秒

2) 消费者端
在客户端,您可以使用断路器和重试的组合来实现所需的弹性解决方案。

断路器可用于防止暂时无法访问的下游系统泛滥。在我们的例子中,这意味着只要速率限制暴露了惩罚,那么断路器就可以从 Closed 进入 Open 状态。这将阻止消费者向下游系统发送请求,而是在客户端立即失败。

Retry-After 标头可用于将状态从 Open 设置为 Half-Open。因此,当暴露的惩罚结束时,断路器允许消费者提出新的请求。

为了避免丢失任何请求,我们可以应用重试逻辑。重试逻辑应该知道断路器。因此,它会尝试发送请求,如果并发请求计数低于阈值,则不会发生任何特殊情况。如果超过阈值,则断路器打开,因此请求将立即失败,稍后需要重新尝试。重试本身也可以利用Retry-After 标头以及指定初始调用和下一次尝试之间的延迟。


请访问Polly project,您可以在其中找到大部分这些技术都是为 .NET 开发人员实现的。我希望这对您有所帮助。

【讨论】:

    猜你喜欢
    • 2012-10-21
    • 2014-08-29
    • 1970-01-01
    • 2012-01-03
    • 2020-11-20
    • 1970-01-01
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多