0%

Golang 的熔断器调研

什么是雪崩效应?

在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因服务提供者的不可用导致服务消费者的不可用,并将不可用逐渐放大的过程。

如果下图所示:A 作为服务提供者,B 为 A 的服务消费者,C 和 D 是 B 的服务消费者。A 不可用引起了 B 的不可用,并将不可用像滚雪球一样放大到 C 和 D 时,雪崩效应就形成了。

另外,在 A 不可用的情况下,由于 B 的重试会放大 A 的请求量,使 A 更加难以恢复。

image.png

熔断器

概念

熔断器模式可以有效防止对故障服务的不断重试,可以使服务调用者继续执行,不用等待错误的修正,或者浪费 CPU 等待超时发生。熔断器模式也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。

能力

熔断器模式为远程服务提供的关键能力:

  • 快速失败
    当远程服务处于降级状态时,应用程序将会快速失败,并防止通常会拖垮整个应用程序的资源耗尽问题的出现。在大多数中断情况下,最好是部分服务关闭而不是完全关闭。
  • 优雅地失败
    通过超时和快速失败,熔断器模式使应用程序开发人员有能力优雅地失败或提供替代方案。
  • 无缝恢复
    熔断器模式可以定期检查所请求的资源是否重新上线,并在没有认为干预的情况下重新允许对该资源进行访问。

实现

  • 关闭状态(Closed)
    在关闭状态下,熔断器会放行请求;通过计数器来判断当前的服务状态,当超过阈值时进入打开状态;当到达设定的间隔时间后会清空计数器,重新开始计数。
  • 打开状态(Open)
    在打开状态下,熔断器会拦截所有请求并返回失败;当到达熔断器的超时时间(timeout)后进入半打开状态。
  • 半打开状态(Half-Open)
    在半打开状态下,熔断器会放行设定的个数个请求,如果请求全部成功,则进入关闭状态;如果有任何失败,则进入打开状态。

image.png
熔断器状态机

熔断器的选型

对比项/框架 sony/gobreaker rubyist/circuitbreaker mercari/go-circuitbreaker
Stars 1.1k 867 193
Forks 79 94 7
Issues Opened 4 10 1
Issues Closed 9 15 0
Last Updated 2019-11-25 2019-10-21 2019-12-27
Latest Version v0.4.1 v2.2.1 /
Complexity Easy Complex Middle
CancelContext Support No Yes Yes
Deadline Support No Yes Yes
Panel Support No Yes No
External Call Support No Yes Yes

github.com/sony/gobreaker

优点:

  • 简单、实现了完整的熔断器
  • sony 出品、稳定、star 最多

缺点:

  • 只支持传入 Func 的方式,如果返回错误则会判定为失败;如果忽略错误,则会在外层丢失错误。
  • 不支持 CancelContext 和 Timeout,可能会将非上游的错误识别为上游错误。

github.com/rubyist/circuitbreaker

优点:

  • 提供了完整的熔断器实现,直接支持错误率和错误个数的配置。
  • 提供了超时和 CancelContext 的支持。
  • 提供了 Panel,在服务中用到多个熔断器的时候可简化实现。
  • 提供了非 Func 方式的支持,便于自定义是否错误和返回正常的数据结构。

缺点:

  • 实现相对复杂,学习成本较高。

github.com/mercari/go-circuitbreaker

优点:

  • 供了完整的熔断器实现
  • 提供了 CancelContext 和 DeadlineContext 的支持。
  • 提供了 IgnoreErr 的支持,可以忽略部分错误。
  • 提供了非 Func 方式的支持,便于自定义是否错误返回正常的数据结构。

缺点:

  • 项目没有发布稳定版本的 tag。
  • issue 少,star 少,可能未得到充分验证。

个人倾向于选择 github.com/rubyist/circuitbreaker