一、雪崩问题及解决方案
1.雪崩问题
微服务之间,一个微服务依赖多个其他的微服务。当一个微服务A依赖的一个微服务B出错时,微服务A会被阻塞,但其他不依赖于B的微服务不会受影响。
当有多个微服务依赖于B时,服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致其他服务都不可用。
那么,依赖于当前服务的其他服务随着时间的推移,最终也会变得不可用,形成级联失败,导致雪崩。
2.解决方案
2.1超时处理
设置超时时间,请求超过设置的时间没有响应,就返回错误信息,不无休止的等待。
2.2仓壁模式(隔离模式)
将系统的请求划分为一个个互不影响的区域。
对不同类型的请求进行隔离,每种类型的隔离互不影响,如果一种类型的请求线程资源耗尽,则对该后续的该类型请求直接返回,不在调用后续资源。
类似的,可以限定每个业务能使用的线程数,避免耗尽整个tomcat的资源,因此也叫线程隔离。
2.3断路器模式(熔断模式)
如果某个目标服务调用慢或有大量超时,此时就会熔断该服务,对于后续的调用请求,不会再继续调用目标服务,直接返回,快速释放资源。
断路器会统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求。
2.4限流
熔断模式和隔离模式都属于出错后的容错处理机制,而限流模式则可以称为预防模式。
限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。
流量控制:限制业务访问的QPS,避免服务因为流量突增而故障。
3.总结
- 什么是雪崩问题?
-
- 微服务之间相互调⽤,因为调⽤链中的⼀个服务故障,引起整个链路都⽆法访问的情况。
- 可以认为:
-
- 限流是对服务的保护,避免因流量突增而故障,进而避免雪崩,是⼀种预防措施。超时处理、线程隔离、降级熔断是在部分服务故障时,将故障控制在⼀定范围,避免雪崩,是⼀种补救措施。
二、服务保护技术对比
在SpringCloud中支持多种服务保护技术:
- Netfix Hystrix
- Sentinel
- Resilience4J
Sentinel | Hystrix | |
隔离策略 | 信号量隔离 | 线程池隔离/信号量隔离 |
熔断降级策略 | 基于慢调用比例或异常比例 | 基于失败比率 |
实时指标实现 | 滑动窗口 | 滑动窗口(基于RxJava) |
规则配置 | 支持多种数据源 | 支持多种数据源 |
扩展性 | 多个扩展点 | 插件的形式 |
基于注解的支持 | 支持 | 支持 |
限流 | 基于QPS,支持基于调用关系的限流 | 有限的支持 |
流量整形 | 支持慢启动 | 不支持 |
系统自适应保护 | 支持 | 不支持 |
控制台 | 开箱即用,可配置规则、查看秒级监控、机器发现等 | 不完善 |
常见框架的适配 | Servlet、Spring Cloud、Dubbo、gRPC等 | Servlet、Spring Cloud Netflix |
三、Sentinel介绍和安装
1.初始Sentinel
Sentinel是阿里巴巴开源的⼀款微服务流量控制组件。官网地址:https://sentinelguard.io/zh-cn/index.html
Sentinel 具有以下特征:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。
- 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
2.安装Sentinel
将从官网下载的jar包放在任意非中文目录下,执行命令:
java -jar sentinel-dashboard-1.8.1.jar
若修改Sentinel的默认端口、账户、密码,可使用以下配置:
- 默认端口 server.port 默认为8080
- 账户 sentinel.dashboard.auth.username 默认为sentinel
- 密码 sentinel.dashboard.auth.password 默认为sentinel
修改端口号的命令为:
java -Dserver.port=8090 -jar sentinel-dashboard-1.8.1.jar
3.访问Sentinel
访问http://localhost:8080(若为修改则为8080,修改后则为自己设置的端口号),即可看到Sentinel的控制台。
登录后发现是空白的,因为还没有和微服务整合到一起。
四、微服务整合Sentinel
我们在shop-order中整合Sentinel,并连接Sentinel的控制台。
1.引入Sentinel依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.在yml文件,配置控制台
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
3.访问
localhost:8091/order/update,触发sentinel的监控。
查看sentinel的控制台
五、流量控制
解决雪崩的方案之一:限流,是为了避免服务因突发的流量而发生故障,是预防措施。
1.簇点链路
当请求进入微服务时,首先会访问DispatcherServlet,然后进入Controller、Service、Mapper,这样的⼀个调用链就叫做簇点链路。簇点链路中被监控的每⼀个接口就是⼀个资源。
默认情况下sentinel会监控SpringMVC的每⼀个端点(Endpoint,也就是controller中的方法),因此SpringMVC的每⼀个端点(Endpoint)就是调用链路中的⼀个资源。
流控和熔断都是针对簇点链路中的资源来设置,因此可点击对应资源后面的按钮来设置规则:
- 流控:流量控制
- 降级:降级熔断
- 热点:热点参数限流,是限流的一种
- 授权:请求的权限控制
2.设置流控规则
要求:给/order/prod/{pid}设置流控规则,QPS不能超过5
2.1在sentinel控制台添加限流规则
其中的QPS为每秒查询率,即每秒的响应次数,也就是最大吞吐能力,QPS=请求数req/秒sec
2.2利用jmeter测试
- 双击jmeter.bat启动jmeter
即可打开jmeter的界面
- 添加线程组
线程数:代表用户数量
时间:代表用户访问时间
10个线程要在2秒内访问完,那每秒就是访问5个线程
QPS=10/2=5,超过了单机阈值2,所以每秒的5个线程只成功2个,剩下的3个线程会请求失败。
循环次数:代表每个用户的访问次数
- 添加http请求
端口号:写的是sentinel中资源/order/prod/{pid}的端口号8091
路径:写的是给资源添加流控规则就写那个资源,/order/prod/{pid}
- 察看结果树
- 启动测试计划
方式一:单击上面任务栏的启动符号(适用于测试计划中只有一个线程)
方式二:右键单击线程启动(适用于测试计划中有多个线程)
结果:可以看到,成功的请求每次只有2个