分布式系统 - 服务治理(四) - 降级 & 熔断
降级和熔断,和限流一样,都可以说属于服务化中流量调控的范畴。主要目的都是一样的:防止大流量冲垮整个集群。
限流属于比较静态的流量调控,一般是配置完就不变,除非集群节点发生变化。而降级一般是运维 / 开发手动触发,熔断是无需配置,自动触发的。
降级和熔断,实现层面没什么好说,应该是比较简单的。说说要注意的点。
熔断
熔断模式(circuit breaker)可以参考电路熔断,如果一条线路电压过高,保险丝会熔断,防止火灾。放到我们的系统中,如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
熔断pattern详细可见参考列表的连接,这里我只说我想到的一些要考虑的情况。
熔断发生在哪
熔断的核心思路是,当服务集群表现不正常的时候,快速失败,保护正常流量,和集群的系统资源。所以这时,应该阻止请求方直接调用那些很可能会调用失败的远程服务或共享资源。这点逻辑发生在调用方。
也就是说,触发熔断后,直接在调用方进程内快速失败。
熔断是怎样触发的
怎样触发熔断?我们在实现的时候,希望做到这样的效果:server不知道自己是否触发熔断,应不应该触发熔断,它尽最大努力处理流量。这个判断由消费方完成。
所以,熔断的的计数,阈值,熔断时间,重试间隔都配置在消费方,让消费方做逻辑判断。
一个简单的判断方法是:没有得到正确处理的请求占比。比如阈值设为60,那么,调用方会对每个请求计数,如果超过60%的请求,调用方都抛出非业务异常,就触发熔断。
熔断的粒度
(消费方的)进程粒度,接口粒度。粒度越小越好,熔断在进程粒度是为了实现简单(可利用juc中的并发工具类,无需用分布式redis)。
另一个考虑是:相同的熔断器有可能被大量并发请求同时访问。熔断器的实现不应该阻塞并发的请求或者增加每次请求调用的负担。降低熔断粒度,也是降低熔断器粒度。
降级
降级好像没什么好说的,也是在zk里配置,从配置中心推到服务提供方生效。注意提供fallback。
参考
- http://www.infoq.com/cn/articles/micro-service-reliability-design
- http://www.infoq.com/cn/articles/architecture-optimization-and-design-the-architect-must-know
- http://www.cnblogs.com/yangecnu/p/Introduce-Circuit-Breaker-Pattern.html
- https://martinfowler.com/bliki/CircuitBreaker.html