gobreaker熔断源码解析
背景
公司内部项目最近需要接入熔断, 正好调研到gobreaker
,和公司内部实现的熔断器,代码量不大, 且非常清晰, 这里记录下其源码分析, 帮助自己更好的理解
熔断架构设计
我们可以看到,主要存在三种状态:
- Close(正常): 此刻正常阶段, 不会影响用户请求
- Open(熔断): 此刻处于熔断阶段, 内部服务不可用
- HalfOpen(恢复阶段): 此刻处于恢复阶段,放行零星请求
状态机流程图如下:
所以我们需要重点关注
- 在什么条件下, 会从[正常阶段], 切换到[熔断中阶段] —> 即动作B
- 在什么条件下, 会从[熔断中],切换到[恢复阶段] —> 即动作B
- 在什么条件下, 会从[恢复阶段], 重新切换到[熔断中阶段]—> 即动作
- 在什么条件下, 会从[恢复阶段], 重新切换到[正常状态]
对gobraker进行源码注释分析:
1 |
|
解答上面的四个问题:
我们进行依次解答:
解答1:
在正常状态下, 当连续失败次数>5次时, 则切换到[熔断中];
这里提供 回调函数, 用户可自己切换条件。
解答2:
在[熔断中]会有冷却期, 当经过固定的冷却期,会自动切换到 [恢复阶段]
冷却期通过timeout
参数进行控制, 在请求前检测,如果达到出发条件,则切换到[恢复阶段]
解答3:
当在[恢复阶段] 陆续检测部分请求,当存在失败情况,或者成功率小于多少,则切换到 熔断中
在[恢复阶段], 如果进行请求, 探测仍然失败, 则继续切换到[熔断中]
解答4,
当在[恢复阶段]陆续检测部分请求,当连续成功次数大于固定值, 或者成功率大于多少,则切换到[正常阶段]
在[恢复阶段], 如果持续进行请求, 并且每次请求都成功, 连续请求成功次数> 最大请求数, 则切换到[正常阶段]
其中的问题有:
- 如果请求时间过长, 请求前后状态已改变, 则对此次请求不进行计数。
- 是按时间段来计数, 并不太精准
- 在恢复阶段, 无法自定义方法更改状态。
对公司内熔断器进行解析:
1 |
|
公司内部实现, 同样采用状态机,在3种状态中轮转。
较gobreak
改进的地方是, 从按固定时间段统计 调整为 按滑动窗口方式来统计。
每秒作为一个桶, 记录每秒钟的成功次数和失败次数。随着时间变化, 每次都将时间窗口向前滑动。
因此我们重新解答上面我们遇到的四个主要问题:
解答1:
通过统计时间窗口中 所有桶的失败数占(失败数+成功数)比例, 统计次数有下限, 比如> xxx次, 如果失败率达到此, 则切换到[熔断中]
解答2:
在[熔断中]会有冷却期, 当超过固定的冷却期,会自动切换到 [恢复阶段]
解答3:
在[恢复阶段], 如果进行请求, 探测达到时间窗口内的失败率, 则继续切换到[熔断中]。 这里最开始放行次数较少, 随着时间增加,放行次数也逐渐增加
解答4,
在[恢复阶段], 探测达到时间窗口内的失败率较小,并且持续固定时间的【恢复阶段】, 则切换到[正常阶段]
这里使用滑动窗口的概念, 因此需要时刻进行滑动窗口:
- 是否需要熔断
- 成功计数时
- 失败计数时
参考文章
- https://zhuanlan.zhihu.com/p/58428026