赞
踩
微服务调用链路中的某个服务故障,引起整个链路中的所有微服务都不可用,这就是雪崩
例如下图中,如果服务 D 挂掉了,那么服务 A 相应的调用服务 D 的业务会阻塞。而此时如果调用服务 D 的业务请求越来越多,就会使得服务 A 的资源被耗尽。这时即使服务 B 的业务可以正常运行,服务 A 调用服务 B 的业务也无法完成
在微服务较多且复杂时,这种雪崩问题会更加明显,会使得整个微服务瘫痪
解决雪崩问题的常见方式有四种:
1.超时处理
设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止等待
这种方式只能缓解雪崩问题,因为假设等待时间为 1s,因为一个服务内部对于请求的处理是串行的,所以此时就是一秒释放一个请求,但是如果进入的请求是每秒两个,那么资源终究还是会被消耗殆尽
2.舱壁模式
限定每个业务能使用的线程数,避免耗尽整个 tomcat 的资源,因此也叫线程隔离
将服务 A 的资源划分成一个又一个独立的线程池,此时假设服务 C 挂掉了,那么服务 A 中只有一个线程池的资源会被耗尽,不会导致所有的资源被耗尽。但这种方式下,资源还是会有一定的浪费
3.熔断降级
由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求
在上图中,如果出现熔断,那么访问服务 D 的请求就会被直接拦截,使得请求被快速释放,这样就不会导致资源被浪费
4.流量控制
限制业务访问的 QPS(每秒处理的请求数量Queries Per Second),避免服务因流量的突增而故障
这种方式是预防雪崩问题的发生,避免某个服务发生故障,防止这个微服务的故障传递到其他的微服务去。而前三种都是已经有服务发生故障了,要怎么去避免这个故障传递到其他服务
这种方式不能完全避免服务的故障,因为高并发只是引起服务故障的原因之一,还有其他的问题,例如网络问题,此时就要用到其他的解决方案
由于雪崩问题,我们需要使用到一些技术来对微服务进行保护,常见的服务保护技术有 Sentinel 和 Hystrix
二者的对比如下:
Sentinel | Hystrix | |
---|---|---|
隔离策略 | 信号量隔离 | 线程池隔离 / 信号量隔离 |
熔断降级策略 | 基于慢调用比例或异常比例 | 基于失败比率 |
实时指标实现 | 滑动窗口 | 滑动窗口(基于 RxJava) |
规则配置 | 支持多种数据源 | 支持多种数据源 |
扩展性 | 多个扩展点 | 插件的形式 |
基于注解的支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 |
流量整形 | 支持慢启动、匀速排队模式 | 不支持 |
系统自适应保护 | 支持 | 不支持 |
控制台 | 开箱即用,可配置规则、查看秒级监控、机器发现等 | 不完善 |
常见框架的适配 | Servlet、Spring Cloud、Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |
线程池隔离跟之前的线程隔离的原理是类似的,也就是将服务划分成多个独立的线程池。而信号量隔离指的是不会为每个业务创建一个线程池,而是会统计当前业务已经使用的线程数,然后进行限制。当达到这个限制时,就会阻止对这个业务的请求,即限制每个业务能使用的线程数量
慢调用比例指的是,如果一个业务大多数情况下耗时比较长,例如10个请求里有8个请求耗时都很长,那么此时就会认为这个业务有问题,可能会拖慢整个服务,所以就可以熔断
Sentinel 是阿里巴巴开源的一款微服务流量控制组件。官网地址:https://sentinelguard.io/zh-cn/index.html
在下载好 Sentinel 的 jar 包后,使用 java -jar
命令运行
启动成功后,可以在浏览器中进入控制台:http://localhost:8080/,默认的用户名和密码都是 sentinel。进入之后的界面如下所示
如果要修改 Sentinel 的默认端口、账户、密码,可以通过下列配置:
配置项 | 默认值 | 说明 |
---|---|---|
server.port | 8080 | 服务端口 |
sentinel.dashboard.auth.username | sentinel | 默认用户名 |
sentinel.dashboard.auth.password | sentinel | 默认密码 |
注意:因为是 jar 包,所以无法修改内部的配置文件,但是可以通过启动命令来修改配置
例如:
java -jar sentinel-dashboard-1.8.1.jar -Dserver.port=8090
在程序中整合 Sentinel 的步骤如下:
1.引入 Sentinel 依赖:
<dependencies> <!--sentinel--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <!--spring-cloud-alibaba--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2021.0.1.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2.编写配置文件 application.yml
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # sentinel控制台地址
server:
port: 8081
3.编写控制层
@RestController
@RequestMapping("/service1")
public class WebController {
@GetMapping("/hello")
public String hello() {
return "hello sentinel";
}
}
4.测试
启动后要先访问微服务的任意端点来触发 Sentinel 监控。Spring MVC 中任意一个 Controller 的接口都是一个端点,因此只要发起一个相应的 HTTP 请求即可
发起请求后,查看 Sentinel 控制台
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。