微服务治理之降级&限流&熔断
前言
从PC互联网到移动互联网,B/S架构演化为多端/S架构。后端服务SOA模式下的重服务或单服务架构,逐渐按功能模块被切分成微服务架构(延伸阅读)。微服务架构确实能解决单服务架构的许多顽疾,比如代码维护难、部署不灵活、稳定性不高、无法快速扩展等。但随着微服务模块的与日俱增,它又带来了一些新的问题需要解决。针对这些问题,Spring Cloud提供了一整套微服务实施方案,包括服务发现、分布式配置、客户端负载均衡、服务容错保护、API网关、安全、分布式服务跟踪等。今天就谈一下微服务容错保护中的三个重要概念:服务降级、服务限流以及服务熔断。
降级、限流以及熔断都是解决服务之间RPC过程出现的异常问题,避免因局部服务问题造成全局服务雪崩。服务间的RPC过程可以简单描述为C⇄S。那么这个过程可能会出现哪些异常情况?降级、限流以及熔断各自解决的是什么异常问题,它们又是如何解决的?
限流
C⇄S 的异常问题:C的请求太多,超出S的服务能力,导致S不可用。DoS攻击就是根据此原理,耗尽被攻击对象的资源,让目标系统无法响应甚至崩溃。解决方案:S对C限流,保护S的服务资源。
限流通常在网关或网络层面实施。对各类请求设置最高的QPS阈值,当请求高于阈值时直接阻断。常用的限流算法有滑动计数,漏斗限流和令牌桶限流三种。
滑动计数限流:按时间片(比如1秒)定义滑动窗口,计数器记录当前窗口的请求次数,达到阈值就限流,窗口滑动后计数器归零。可采用循环队列数据结构实现。
漏斗限流:维护一个队列,所有请求进队列,按FIFO服务,队满溢出则丢弃请求。
令牌桶限流:按固定速率往桶中存入令牌,服务前先从桶中取令牌,取到令牌才服务。
降级
C⇄S的异常问题:S自身出现异常,或者由于资源有限需要对部分C请求故意表现为异常(类似限流),为了不影响其他服务功能,主动关闭服务的一些功能。
降级的反义词是升级,升级需要代码开发,降级类似于把部分代码注释掉,牺牲部分功能。这要求S在实现时,需要具备感知异常的能力,并对关键逻辑实现开关控制。实际场景中,对异常的『感知』通常由熔断器实现。
熔断
C⇄S的异常问题:C发现S出现异常(比如大量超时),主动出击,暂停对S的请求。
C对S熔断后,那么原本需要调用S实现的逻辑怎么办呢?可以用mock数据、缓存数据、缺省数据等替代,或者干脆就是抛异常返回错误信息。此时,如果C也是一个服务,它相当于做了服务降级。所以我们经常看到服务熔断和服务降级一起出现(Hystrix的断路器在实现时就是把熔断和降级方案打包实现的)。但本质上它们不是一回事,降级发生在S,熔断发生在C。之所以配合实现,是因为许多微服务模块同时承担C和S两种角色。
熔断的设计有两个关键点:① 判断何时熔断,② 何时从熔断状态恢复。
判断何时熔断:通常使用无锁循环队列计数来实现。C对每次请求S的正常、异常(失败、拒绝、超时)返回计数,当异常返回次数超过设定阈值时进行熔断。
何时从熔断状态恢复:处于熔断状态时,C每隔一段时间(比如5秒),允许部分请求通过,若这部分请求正常返回,就恢复熔断。
总结
降级、限流以及熔断都是解决服务之间RPC过程的异常问题,保证服务稳定性的手段。降级和限流发生在S端,熔断发生在C端。在实际场景中,它们通常会配合实现,特别是熔断和降级。熔断决定何时降级,降级是服务在熔断状态下的对外表现。Spring Cloud全家桶中的Hystrix就是一个优秀的熔断&降级组件。
-- End --
延伸阅读