5. 服务容灾
前言
参考资料:
《Spring Microservices in Action》
《Spring Cloud Alibaba 微服务原理与实战》
《B站 尚硅谷 SpringCloud 框架开发教程 周阳》
当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作;
1. 服务容灾基础知识
1.1 由一个服务资源耗尽引发的连锁反应
- A 服务调用 B 服务,B 服务调用 C 服务;
- 当 C 服务出现调用缓慢问题是,影响 B 服务的响应;B 服务又会影响 A 服务,导致其他服务不可用;
1.2 服务雪崩效应
- 在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,但是由于网络原因或者自身的原因,服务并不能保证服务的 100% 可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务堆积,最终导致服务瘫痪;
- 在分布式系统中,由于网络原因或自身的原因,服务一般无法保证 100% 可用。如果一个服务出现了问题,调用这个服务就会出现线程阻塞的情况,此时若有大量的请求涌入,就会出现多条线程阻塞等待,进而导致服务瘫痪;
1.3 四种客户端弹性模式
- 客户端负载均衡模式(client load balance):让客户端从服务注册中心查找服务的所有实例,然后缓存服务实例的物理位置;
- 断路器模式(circuit breaker):远程服务调用时间太长,断路器将会介入并中断调用 ;
- 后备模式(fallback):远程服务调用失败时,服务消费者将执行替代代码路径, 并尝试通过其他方式执行操作,而不是生成一个异常;
- 舱壁模式(bulkhead):每个远程资源、都是隔离的,并分配给线程池;
1.4 服务容灾的几种解决方案
- 服务隔离:即舱壁模式。将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。常见的隔离方式有:线程池隔离和信号量隔离;
- 服务超时:在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过这个时间,下游未作出反应,就断开请求,释放线程;
- 服务降级:即后备模式。服务提供一个托底方案,一旦服务无法正常调用,就使用托底方案;
- 服务熔断:即断路器。上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。一种“牺牲局部,保全整体”的策略;
- 服务限流:限制系统的输入和输出流量已达到保护系统的目的;
1.5 服务降级的参考指标
- 服务降级需要有一个参考指标,一般来说有以下几种常见方案;
- 平均响应时间:比如15内持续进入5个请求,对应时刻的平均响应时间均超过阈值,那么接下来在一个固定的时间窗口内,对这个方法的访问都会自动熔断;
- 异常比例:当某个方法每秒调用所获得的异常总数的比例超过设定的阈值时,该资源会自动进入降级状态,也就是在接下来的一个固定时间窗口中,对这个方法的调用都会自动返回;
- 异常数量:和异常比例类似,当某个方法在指定时间窗口内获得的异常数量超过闽值时会触发熔断;
1.6 服务限流的作用
- 限流的主要目的是通过限制并发访问数或者限制一个时间窗口内允许处理的请求数量来保护系统,一旦达到限制数量则对当前请求进行处理采取对应的拒绝策略,比如跳转到错误页面拒绝请求、进入排队系统、降级等;
- 从本质上来说,限流的主要作用是损失一部分用户的可用性,为大部分用户提供稳定可靠的服务;
- 实际开发中的限流应用:
- 在 Nginx 层添加限流模块限制平均访问速度;
- 通过设置数据库连接池、线程池的大小来限制总的并发数;
- 通过 Guava 提供的 Ratelimiter 限制接口的访问速度;
- TCP 通信协议中的流量整形;
1.7 常见的几种限流算法
1.7.1 计数器算法
- 一种比较简单的限流实现算法;
- 原理:在指定周期内累加访问次数,当访问次数达到设定的闽值时,触发限流策略,当进入下一个时间周期时进行访问次数的清零;
- 存在临界问题:前一个周期的后半部分与后一个周期的前半部分的总访问次数可能超过阈值;
1.7.2 滑动窗口算法
- 是一种流量控制技术,在 TCP 网络通信协议中,就采用了滑动窗口算法来解决网络拥塞的情况;
- 原理:在固定窗口中分割出多个小时间窗口,分别在每个小时间窗口中记录访问次数,然后根据时间将窗口往前滑动并删除过期的小时间窗口。最终只需要统计滑动窗口范围内的所有小时间窗口总的计数即可;
- 该算法解决了临界问题,Sentinel 采用滑动窗口算法来实现限流;
1.7.3 令牌桶算法
- 是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法;
- 原理:对于每一个请求,都需要从令牌桶中获得一个令牌,如果没有获得令牌,则需要触发限流策略;
- 由于令牌桶有固定的大小,当请求速度小于令牌生成速度时,令牌桶会被填满。所以令牌桶能够处理突发流量,也就是在短时间内新增的流量系统能够正常处理,这是令牌桶的特性;
1.7.4 漏桶限流算法
- 主要作用是控制数据注入网络的速度,平滑网络上的突发流量;
- 原理:在漏桶算法内部同样维护一个容器,这个容器会以恒定速度出水,不管上面的水流速度多快,漏桶水滴的流出速度始终保持不变;
- 消息中间件就使用了漏桶限流的思想;
- 请求速度大于漏桶流出水滴的速度时,触发限流策略;
- 与令牌桶算法的区别:漏桶无法处理短时间内的突发流量,漏桶限流算法是一种恒定速度的限流算法;
1.8 利用 Postman 模拟请求高并发场景
- Postman 里新建多线程集合组;
- 右键添加请求
- 将访问地址添加进新新线程组;
- 设置多线程组的运行状态;
- 使用 postman 密集访问 testA,下面配置的含义是:
- 20个线程每次间隔 0.3s 访问一次;
1.9 目前几种流行的服务降级组件对比
比较项 | Hystrix | Sentinel | Resilience4j |
---|---|---|---|
贡献者 | Netflix | Alibaba | Apache 基金会 |
隔离策略 | 线程池隔离/信号量隔离 | 信号量隔离(并发线程数限流) | 信号量隔离 |
熔断降级策略 | 基于异常比率 | 基于响应时间、异常比率、异常数 | 基于异常比率、响应时间 |
实时统计实现 | 滑动窗口(基于 RxJava) | 滑动窗口(LeapArray) | Ring Bit Buffer |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
扩展性 | 插件的形式 | 多个扩展点 | 接口的形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
限流 | 有限的支持 | 基于 QPS,支持基于调用关系的限流 | Rate Limiter |
流量整形 | 不支持 | 支持预热模式、匀速器模式、预热排队模式 | 简单的 Rate Limiter模式 |
系统自适应保护 | 不支持 | 支持 | 不支持 |
控制台 | 简单的监控查看 | 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 | 不提供控制台,可对接其它监控系统 |
2. Hystrix
Hystrix 是一个延迟和容灾库,旨在隔离远程系统、服务和第三方库的访问点,停止级联故障,并在故障不可避免的复杂分布式系统中实现弹性;
3. Sentinel
Sentinel 是面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从限流、流量整形、服务降级、系统负载保护等多个维度来帮助我们保障微服务的稳定性;
4. Resilience4j
Resilicence4j 一款非常轻量、简单,并且文档非常清晰、丰富的熔断工具,这也是Hystrix官方推荐的替代产品。不仅如此,Resilicence4j 还原生支持Spring Boot 1.x/2.x,而且监控也支持和 prometheus 等多款主流产品进行整合