背景
你是否有过这样的经历:家里停电了,但转头发现别人家却还有电。
这种情况,十有八九是电闸中的保险丝烧了,那保险丝为什么会烧掉呢?
因为,当电路发生故障或异常时,伴随着电流不断升高,保险丝的热度也会随之升高,到了一定的热度保险丝便会被熔断,从而使电路被断开。
那它有什么作用?显然是具有保护作用。你想想,假设是因为你家同时开启了很多大功率的设备导致的电流不断升高,此时如果保险丝不自熔断,那么会很容易引起电线外表过热发烫直至酿成火灾或者导致电器被烧坏。
保险丝也被称之为熔断器,不仅仅电闸中有熔断器,其它家用电器如洗衣机、电饭煲、空调中也都有相应的熔断器,其作用都是在保护电器本身不受外部电路故障的影响。
同样,在分布式的微服务架构中,我们也需要为服务配备一个熔断器,用于保护服务不受外部故障的影响。
为什么?微服务架构的应用系统像一张网,服务是网中的节点,服务调用是网中的关系。假设网中的某个服务发生故障或异常如请求超时,如果不对它的上游服务加以保护,那么该故障会借助"网"蔓延至上游服务,
导致上游服务的请求也超时;接下来,上游服务又将故障以相似的方式往上传播给它的上游服务,如此这般直至这个网中的服务都受影响,从而使整个系统处于完全不可用的状态。
这便是由单点故障所引起的连级故障,如果不切断故障的传播那么对整个系统的影响是灾难性的。
问题
在分布式的系统中,个别服务出现调用超时、不可用等故障是正常的。
但因为有些故障具有"传播性",如果其它服务不具备切断故障的自保能力,那么就不可避免的会受故障的影响。
所以,受电闸、电饭煲等电器中熔断器的启发,人们为微服务架构的应用引入了熔断这一概念。
熔断机制其实非常的简单,即:在上游服务调用下游服务时,如果下游服务的失败率超过一定的阀值,那么上游服务就不再调用下游服务,从而保护服务自身不受故障的影响。
在微服务中,实现熔断机制的东西被称为熔断器。
方案
avatar熔断器位于上下游服务或消费者与提供者之间,当消费者调用提供者之前,会询问熔断器是否可以执行调用操作,如果提供者的调用失败率超过预设的阀值,那么熔断器便会打开,打开意味着调用操作不允许执行。熔断器通过下面三种状态来控制调用操作是否可执行。
avatar关闭状态(Closed):当熔断器处于该状态时,调用操作可以正常执行,但会用一个计数器来统计一段时间内调用操作的失败次数,当然也会统计总次数和成功次数。
打开状态(Open):当一段时间内调用操作的错误率(失败次数/成功次数+失败次数)大于设定的阀值时,熔断器会进入打开状态,需要等待熔断时间超时;此时,调用操作不再被允许执行。
半开状态(HalfOpen):当等待时间超过熔断时长时,熔断器会进入半开状态;此时,会放行某个调用操作,如果执行成功那么熔断器进入关闭状态,如果执行失败那么熔断器再次回到半开状态。
回退策略
avatar无论是熔断器处于打开状态还是执行操作失败,服务此时已经发生了错误,是将异常直接返回给消费者呢?还是有补偿机制可以弥补错误?这都需要根据具体的情况选择不同的应对策略,常见的回退策略有下面几种。
快速失败(fail-fast):直接抛出异常,适用于错误无法补救的场景,如:支付、下单等。
故障沉默(fail-silent):返回空值或缺省值如空字符、空数组、空列表等,适用于一些可降级的功能,如猜你喜欢、商品推荐等不影响用户使用的功能。
缓存(cache):放回缓存数据,适用于读接口并且脏数据对用户的影响不大,如:订单列表,收藏等。
总结
在分布式架构中,因为下游服务的某些故障具有传播性,所以上游服务需要具有即时熔断故障对其影响的能力,从而避免故障一层层往上传播引起连级故障致使整个系统不可用的风险。
网友评论