从状态机看熔断器
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc
1. 引言
提到熔断器,大家总会提到Hystrix
.但是Hystrix似乎给人一种云里雾里的感觉. 前段时间,我维护的服务也增加了熔断机制,本文中,我将结合我自己的理解来谈谈熔断。
我们选择的是rubyist/circuitbreaker, 这个库的代码可读性比Hystrix
以及afex/hystrix-go要高不少,也推荐一下。
2. 关于熔断
如上图所示,熔断器把客户端
和服务提供方
隔离开来,在客户端
调用服务提供方
接口时,对服务提供方
的服务质量进行监测。如果服务提供方
出现问题,则将触发熔断。 这里引出了几个问题
问题1:什么样的情况,可以理解为服务提供方
出现了问题?
问题2:触发熔断会怎么样?
问题3:熔断打开以后,如何关闭?
3. 熔断器与状态机
在熔断器内部有3种状态
1. Closed
熔断器关闭
客户端
正常访问服务提供方
2. Open
熔断器打开
阻断客户端
对服务提供方
的访问
3. Half Open
熔断器半开
熔断器开始重新判断是否需要继续熔断
熔断器只是简单在状态机的状态之间切换,至于熔断之后,如何处理客户端
的请求,则是更上层业务代码的事情
结合rubyist/circuitbreaker
,我来谈谈状态之间的装换条件
3.1 Closed
-> Open
服务提供方
出现异常
1) 连续发生threshold个错误,立即熔断(ConsecutiveTripFunc)
2)单位时间请求数达到minSamples个,错误率达到rate,即熔断(RateTripFunc)
3)单位时间发生threshold个错误,立即熔断(ThresholdTripFunc)
这里的错误完全是由业务系统来定义,可能是
a) 后端接口的响应严重超时
b) 后端服务返回异常的错误(如HTTP协议 5xx)
c) RPC返回有异常的错误码
当熔断器处于Open
状态,客户端
对服务提供方
的访问被阻断了。我们该如何响应客户端的请求?
通常而言,可以有这么几种做法
1. 直接返回给客户端失败信息
2. 将返回降级后的结果
比如针对读请求,可以返回固定值,或者cache中的历史数据
3.2 Open
-> Half Open
在熔断一段时间后,服务提供方
的服务可能已经恢复了。那么怎么感知到服务提供方
的服务已经恢复。
rubyist/circuitbreaker
的做法是使用定时器
(2种实现,ExponentialBackOff和ConstantBackOff),每当定时器的设定的时间到达,熔断器的状态从Open
切换到 Half Open
3.3 Half Open
-> Closed
/ Half Open
-> Open
在Half Open
状态,熔断器重新探测(计算)服务提供方
的健康情况进行检测。
如果服务提供方
的服务已经恢复,则熔断器切换到Closed
状态,否则切换到Open
4 总结
最后我们来聊聊熔断的好处。如果服务提供方
已经过载,比如响应超时严重,继续对它进行请求,可能会使得客户端
因超时而请求失败。客户端
因为失败可能会执行多次重试,这种重试反而极有可能压垮服务提供方
。
另外严重的超时还会影响用户的体验,而fail fast
,适当的降级,可以提高用户的整体体验。
好文