服务容错详解
为什么要引入服务容错组件
随着微服务架构的普及和项目的实际落地,服务容错的概念逐渐流行。开发人员更加关注服务的稳定性,像 Hystrix
、Sentinel
这些用于保护服务稳定运行的组件也开始涌现和发展,在保证服务的稳定性和系统的高可用中扮演着重要的角色。
高可用(High Availability
,HA
)的主要目的是保障 “业务的连续性”,即在用户眼里,系统永远是正常(基本正常)对外提供服务的,高可用是架构设计和系统搭建时必须要考虑的一点。而谈到高可用,很多开发人员脑海中出现的第一个技术就是 “搭建集群”,通过搭建集群能够有效避免由于单点故障导致的系统不可用。集群化是保障系统 “高可用” 的基本操作,不过只是搭建集群还不够,还要对系统做更多的优化工作,如优化业务代码、引入缓存、引入异步操作的逻辑、优化 SQL 语句、增加服务器的物理配置等。
上述的系统优化手段已经极大地提升了系统的健壮性,但是在微服务环境下,由于硬件、网络、机器性能、算法、程序等各方面的影响,运行异常的情况也在显著增加,如果不做好异常保护,微服务架构就像空中楼阁一样随时可能崩溃。现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路,如图 11-1 所示。

即使单个服务出现了不可用的情形,在链路调用中也会产生放大的效果。复杂链路上的某一环不稳定,就可能层层级联,最终导致整个链路都不可用。
这就是微服务系统高可用性的杀手——“服务雪崩”,如图 11-2 所示。“雪崩”一词指的是山地积雪由于底部溶解等原因造成的突然大块塌落的现象,具有很强的破坏力。服务雪崩效应是一种因 “服务提供者的不可用”(原因)导致 “服务调用者不可用”(结果),并产生级联效应将 “不可用” 逐渐放大的现象,最终导致整个系统不可用。

服务雪崩是一种笼统的描述,生产环境中会出现如下这些不稳定的状况。
-
活动期间导致瞬时流量过大,超出服务器物理机的承受范围,进而导致无法正常处理请求,用户只能看到一个空白的页面却无法操作。
-
热点数据击穿缓存,导致
DB
层被打垮,用户无法获取正常的数据,也无法进行正常的操作。 -
调用端服务被不稳定的下游服务拖垮,导致某条调用链路卡死,用户会看到某个功能一直处于不可用的状态。
为了避免出现上述问题,同时给微服务系统加上一层防护,保障系统的稳定性和高可用性,引入了服务容错。
服务容错落地方案:流量控制与降级熔断
了解了为什么要引入服务容错后,接下来笔者讲解服务容错具体的落地方案。
以服务雪崩效应为例,这种对系统造成破坏性伤害的状况有两个主要因素。
-
瞬时流量太大,超出了系统的负载。
-
部分服务响应不及时,进而逐步拖垮了上游服务。
因此,服务容错的落地方案就要针对这两个问题进行处理。首先进行流量控制,可以采用限流的方式控制请求数量,让请求流量有序地进入应用,并保证流量在一个可控的范围内。其次是针对服务内部响应慢的问题引入断路器模式,当调用链路中某个服务出现不稳定的情况(如调用一直超时或异常比例较高)时,对这个服务的调用进行限制,并让请求快速失败,避免影响系统中其他的服务。
有了解决问题的方案,就可以讲解具体落地实现了,也就是服务容错章节的主角——Sentinel
。它是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度帮助开发人员保障微服务的稳定性。
流量控制
请求流量具有随机性且很难准确预测,前一秒可能风平浪静,后一秒就可能出现流量洪峰,然而系统的容量总是有限的,如果突然而来的流量超过了系统的承受能力,就可能导致请求处理不过来,堆积的请求处理缓慢,物理服务器的 CPU
使用率和内存使用率持续升高,最后导致系统崩溃。因此需要针对这种突发的流量进行限制,在尽可能处理请求的同时来保障服务正常运行,这就是流量控制。
Sentinel
组件可以根据需要把随机的请求调整成合适的形状,即流量整形,如图 11-3 所示。

Sentinel
组件中的流量控制有以下几个角度。
-
资源的调用关系,如资源的调用链路、资源和资源之间的关系。
-
运行指标,如
QPS
(Queries Per Second
,每秒查询率)、线程池、系统负载等。 -
控制的效果,如直接限流、冷启动、排队等。
在后续章节中对这些内容进行详细的介绍。
降级熔断
微服务架构都是分布式的,通常有多个服务实例。在进行具体的功能实现时,一个服务常常会调用别的下游服务。然而,这个被依赖的服务的稳定性是不能完全保证的。如果依赖的服务出现了不稳定的情况,则上游服务对该服务的请求响应时间变长,异常调用的数量积累起来可能会拖垮上游服务,也就是人们常说的 “一颗老鼠屎坏了一锅粥”。因此需要对不稳定的依赖服务进行降级熔断,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。
所谓降级,是指当服务调用发生了响应超时、服务异常等情况时,跳出当前的执行方法,在服务内部执行一段 “降级逻辑”,在具体的编码中就是多写一个兜底方法,在这个方法里可以什么都不做,也可以直接返回提示信息或做其他处理。
所谓熔断,就是直接拒绝访问。一般是根据请求失败率或请求响应时间做熔断。熔断好比家里的漏电保护器,线路过热就会跳闸,以免烧坏线路。在 Sentinel
组件中,可以根据实际情况在控制台进行熔断规则的配置,可选的维度有异常数、异常比例和平均响应时间。
提到微服务技术栈中的熔断组件,其实开发人员对 Netflix
套件中的 Hystrix
更加熟悉,毕竟它也是红极一时的服务容错方案。不过,随着 Netflix
套件进入维护期,Hystrix
基本上已经停止更新了。后来 Sentinel
组件、Resilience4j
组件逐渐成为 Hystrix
在服务容错领域的替代方案。
Sentinel
组件、Hystrix
组件、Resilience4j
组件的对比见表11-1。


Resilience4j
组件在国外相对来说用得较多。Hystrix
组件处于维护阶段,使用率在逐渐降低。
通过组件间的对比,也能够看出 Sentinel
是一种更优的落地方案。