微服务保护 Sentinel
1.雪崩问题
(1)何为雪崩问题
在微服务中,服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务:
如图:如果服务提供者I出现故障,当前的应用的部分业务因为依赖I,所以也会发生故障。
但是,其它不依赖于服务I的业务似乎不受影响。
真的是这样吗?答案是否定的。
因为此时I的业务请求被阻塞,用户得不到响应,则tomcat的这个线程不会被释放,越来越多的用户请求到来,越来越多的线程会阻塞。由于服务器支持的线程和并发数优先,请求一直阻塞,会导致服务器资源耗尽,从而导致其他服务都不可用,那么当前的服务也就不可用了。
那么,依赖于当前服务的其他服务随着时间的推移,最终也都会变得不可用,形成级联失败,雪崩就这样发生了!
(2)咋解决雪崩问题呢?
解决雪崩问题常见的方式有四种:
(i)超时处理:设定一个超时时间,请求超过一定时间没有相应就返回错误信息,不会无休止的等待
(ii)仓壁模式:限定每个业务能使用的线程数,避免耗尽整个tomcat的资源,因此也叫线程隔离
(iii)断路器模式:由断路器统计业务执行的异常比例没,如果超过阈值则会熔断该业务,拦截访问该业务的一切请求。
断路器会统计访问某个服务的请求数量,异常比例:
当访问服务D的请求异常比例过高,任务服务D有导致雪崩的风险,会拦截访问服务D的一切请求,形成熔断:
(iv)限流:即流量控制:限制业务访问的QPS(query【请求】per second 每秒请求量),避免服务因流量的突增而故障
(3)总结:
雪崩问题:微服务之间相互调用,因为调用链中的一个服务故障,引起整个链路都无法访问的情况。
解决措施:限流是对服务的保护,避免因瞬间高并发流量而导致服务故障,进而避免雪崩,是一种预防措施。而其他三种方法是在部分服务发生故障时进行的一种控制行为,是一种补救措施。
2.有哪些进行服务保护的技术呢?
在SpringCloud中支持多种服务保护技术:
早期流行的是Hystrix框架,但是目前国内使用的最广泛的还是阿里巴巴和Sentinel框架。
3.Sentinel安装
Sentinel是阿里巴巴开源的一款微服务流量控制组件。
Sentinel主要实现了限流、仓壁模式、降级熔断三种解决措施
安装步骤:
(1)下载:可以去GitHub下载,下载下来是一个jar包
(2)运行:将该jar包放到非中文目录下,执行下面的命令:
java -jar sentinel-dashboard-1.8.1.jar
注意,这时可能会启动失败,报这个错误:java.lang.IllegalStateException: Cannot load configuration class: com.alibaba.csp.sentinel.dashboard.DashboardApplication
这时因为该版本的sentinel指定的jdk版本与你现在电脑使用的jdk版本不一致,这个1.8.1版本的jar包要求Build-JDK是:
要解决此办法,需要下载相应的jdk,但是我使用的是1.8.0_131同样是可以的,应该是保证jdk1.8即可;下载好相应的jdk后,先控制台执行此命令:
set Path=D:\sdk\jre1.8.0_131\bin
然后再执行
java -jar sentinel-dashboard-1.8.1.jar
就能启动成功了。
如果要修改Sentinel的默认端口、账户、密码,可以通过下列配置:
比如修改端口:
java -Dserver.port=8090 -jar sentinel-dashboard-1.8.1.jar
访问:
访问localhost:8080即可看到控制台,默认用户名和密码都是sentinel,这时候sentinel还没与我们的微服务进行整合。
4.微服务整合Sentinel
我们在order-service中整合Sentinel,并连接Sentinel的控制台,步骤如下:
(1)引入sentinel依赖:
<!--引入sentinel依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
(2)配置控制台地址:
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8090
(3)访问微服务的任意断电,触发sentinel监控
5.流量控制
我们先从对微服务雪崩问题的预防:流量控制开始学习。
(1)簇点链路
簇点链路就是项目内的调用链路,Controller->Service->Mapper,这就形成了一个链路,链路中被监控的每个接口就是一个资源。默认情况下sentinel会监控SpringMVC的每一个端点(Endpoint),因此SpringMVC的每一个端点(Endpoint)就是调用链路中的一个资源。
(2)快速入门
流控、熔断都是针对簇点链路中的资源来设置的,因此我们可以点击对应资源后面的按钮来设置规则。
点击流控按钮后会弹出一个窗口:
其含义是限制/order/{orderId}这个资源的单机QPS为1,即每秒只允许1次请求,超出的请求会被拦截并报错。
(3)流控模式
再添加限流规则时,点击高级选项,可以选择三种流控模式:
-
直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也就是默认的模式
-
关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
给谁限流,就给谁加规则
案例:当访问order/update访问QPS超过5,对order/query做限流
步骤:对order/query做限流,就给它加规则:
点击新增,然后通过JMeter就可以进行测试了。
-
链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流
例子:例如有两条链路:
/test1 -> /common
/test2 -> /common
也就是有两条链路都能访问到common资源,如果只希望统计从/test2进入到/common的请求,则可以这样配置:
案例:
注:
(i)Sentinel默认只标记Controller中的方法为资源,如果标记其它方法,需要利用@SentinelResource注解,比如我们标记Service中的一个方法:
@SentinelResource("goods")
public String queryGoods(){
return "查询商品";
}
(ii)Sentinel默认会将Controller方法做context整合,导致链路模式的流控失效,需要修改application.yml,添加配置:
spring:
cloud:
sentinel:
web-context-unify: false # 关闭context整合
随便设置这两个任意一个goods都行,这两个goods是同一个资源。
(4)流控效果
- 快速失败:达到阈值后,新的请求会被立即拒绝并抛出FlowException异常,是默认的处理方法;
- warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常,但是这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值;
- 排队等待:让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长
(i)warm-up 预热模式:warm-up是应对服务冷启动的一种方案(加入一个服务器的QPS是10,当这个服务器刚刚启动时,不能让访问它的QPS瞬间达到10,这样会损伤服务器,而是慢慢的加大访问它的QPS),请求阈值初始值是threshold/coldFactor,持续指定时长后,逐渐提高到threshold值,而coldFactor的默认值是3。
例如:我设置的QPS的threshold是10,预热时间为5秒,那么初始阈值就是10/3=3,在5秒后逐渐增长到10。
(ii)排队等待:当请求超过QPS阈值时,快速失败和warm up会拒绝新的请求并抛出异常,而排队等待则是让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。后来的请求必须等待前面的请求执行完成,如果请求预期的时间超过最大时长,则该请求会被拒绝。
例如:QPS=5,意味着每过200ms执行一个请求,如果设置timeout(最大时长)= 2000,意味着等待超过2000ms的请求会被拒绝并抛出异常,也就是理论上第12个请求会被拒绝并抛出异常。
比如某一时间没有一个QPS请求进入服务器,但是突然一秒来了5个QPS请求,由于排队等待,它们并不能一股脑的进入服务器,而是再队列中每隔200ms进入一个,进入的QPS无论怎么波动,出去的QPS一定是一个平缓的状态,起到流量整型的作用。
6.热点参数限流
(1)概念:之前的限流是统计访问某个资源的所有请求,判断是否超过QPS阈值,而热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值。
参数索引:这里是0,指当前资源的参数列表中的第0号索引对应的参数,就是第一个参数。
(2)例外配置:
在热点参数限流的高级选项中,可以对部分参数设置例外配置:
含义:结合(1)里面的配置,这里的含义是对0号的long类型参数限流,每一秒相同参数的QPS不能超过5,有两个例外:
- 如果参数值是100,则每1秒允许的QPS为10
- 如果参数值是101,则每1秒允许的QPS为15
(3)案例:
注意:热点参数限流对默认的SpringMVC资源是无效的,也就是Controller中的方法是没法进行热点参数限流设置的,比如order/{orderId},只有通过@SentinelResource注释的资源才能设置热点参数限流。
步骤:(i)给Controller中的order/{orderId}方法添加@SentinelResource注解
@SentinelResource("hot")
@GetMapping("{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
// 根据id查询订单并返回
return orderService.queryOrderById(orderId);
}
(ii)重新部署启动访问,然后在sentinel客户端的簇点链路中找到这个资源
注意,点击簇点链路中某资源的热点按钮是不会有高级选项这个设置的,我们需要点击zuoce的热点规则,然后点击新增热点规则才会有高级选项这个设置:
未完待续
标签:其一,服务,请求,--,sentinel,限流,链路,Sentinel,QPS From: https://www.cnblogs.com/Noob-Green-Hand/p/17397834.html