sentinel简单理解:
通过控制请求的流量来提高服务的稳定性
Sentinel 分为两个部分:
1、核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
2、控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
sentinel的使用
一、准备
1. 下载sentinel的jar包
2. 启动sentinel
将jar包放到任意非中文目录,执行cmd命令:
java -jar sentinel-dashboard-2.0.0-alpha-preview.jar
如果要修改Sentinel的默认端口、账户、密码,可以通过下列配置:
配置项 | 默认值 | 说明 |
---|---|---|
server.port | 8080 | 服务端口 |
sentinel.dashboard.auth.username | sentinel | 默认用户名 |
sentinel.dashboard.auth.password | sentinel | 默认密码 |
例如,修改端口为8090:
java -Dserver.port=8090 -jar sentinel-dashboard-2.0.0-alpha-preview.jar
3. 访问sentinel
访问 localhost:端口号 ,就可以看到sentinel的登录页面了。
需要输入账号和密码,默认都是:sentinel
登录后,发现一片空白,什么都没有,因为还没有监控任何服务。
另外,sentinel是懒加载的,如果服务没有访问,看不到该服务信息。
4. 整合sentinel
1、引入sentinel依赖
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2、配置控制台
修改服务的application.yml文件,添加下面内容
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # 配置sentinel控制台地址
3、访问服务的任意接口
打开浏览器,访问对应的 localhost:端口号/请求路径,这样才能触发sentinel的监控。
然后再访问sentinel的控制台,就能看到效果了
二、使用
1. 流控模式
在添加限流规则时,点击高级选项,可以选择三种流控模式:
1、直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式
2、关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
3、链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流
我们一种一种来看,首先访问我们需要进行流控的接口,
比如我的接口 localhost:10100/api/user/findUserByUserId/1
此时可以在控制台的簇点链路中看到对应的请求路径,在点击流控按钮进行配置
1、直接模式
QPS : 每秒请求数量
在此页面中其他的默认都设置好了,我们只需要将QPS设置成5,代码每秒只能通过5个请求,其他全部被拦截
配好之后就会跳转到流控规则页面,此时就能看到我们添加的流控规则
测试一下,访问对应地址,一秒钟刷新5次以上,出现以下效果
2、关联模式
统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
此时我们需要再创建一个接口来演示 localhost:10100/api/user/updateUserById
在控制台中设置关联模式,设置阈值5,填写关联资源
将我们之前配置的规则删除,避免影响当前测试
在测试前我们需要去下载一个工具来帮助我们进行测试,因为我们没办法同时发送多个请求
jmeter的下载与使用
jmeter : Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具,用于对软件做压力测试。
①下载
下载地址:Index of /dist/jmeter/binaries
本测试用的是apache-jmeter-5.6
②使用
将压缩包解压完之后进入bin目录下,可以看到一个ApacheJMeter.jar的文件
通过cmd命令运行此文件
java -jar ApacheJMeter.jar
进入jmeter主页面
右键测试计划,创建一个线程组
进行配置1000个线程,100秒发完,也就是10个/秒,QPS = 10 ,超过了我们在sentinel设置的阈值5
右键刚刚添加的线程组,创建一个HTTP请求
进行配置,这里需要配置的是/api/user/updateUserById,因为我们在sentinel中关联是这个路径
右键HTTP请求创建一个结果树便于我们查看结果状态
配置好后,右键线程组启动
此时会让我们保存
保存在你jmeter的bin目录下即可
查看结果树,请求全部访问成功
此时再来访问配置的另一个地址,访问失败
因为我们配置了关联模式,当B接口的访问数量超过了我们设定的阈值,A接口是不能进行访问的,避免A与B进行资源的争抢,导致B操作失败
使用场景:比如用户支付时需要修改订单状态,同时用户要查询订单。 业务要求是优先支付和更新订单的业务,再查询订单。因此当修改订单业务触发阈值时,需要对查询订单业务限流。
3、链路模式
只针对从指定链路访问到本资源的请求做统计,判断是否超过阈值,如果超过阈值对从该链路请求进行限流。
再写两个Controller方法去调用同一个Service方法
@GetMapping(value = "/save")
public String save() {
userService.queryUsers();
System.out.println("保存用户");
return "订单保存成功" ;
}
@GetMapping(value = "/query")
public String query() {
userService.queryUsers();
System.out.println("查询用户");
return "查询用户成功" ;
}
service方法上需要加上@SentinelResource 注解标记并设置value值,作为一个sentinel监控的资源(默认情况下,sentinel只监控controller方法),设置的value值就是sentinel中的资源名
@Override
@SentinelResource("users")
public void queryUsers(){
System.err.println("查询用户");
}
更改application.yml文件中的sentinel配置
链路模式中,是对不同来源的两个链路做监控。但是sentinel默认会给进入spring mvc的所有请求设置同一个root资源,会导致链路模式失效。因此需要关闭这种资源整合。
spring:
cloud:
sentinel:
web-context-unify: false # 关闭context整合
可以看到每一个路径下都出现了一个users资源
点击users资源后面的流控按钮,添加链路流控规则,阈值设置为2,资源入口设成/api/user/query
只统计从/api/user/query进入/users的资源,QPS阈值为2,超出则被限流。而从/api/user/query进入/users的资源则全部放行
在jmeter中测试
200个线程,50秒内发完,QPS为4,超过了我们设定的阈值2。
一个http请求是访问/api/user/save
另一个是访问/api/user/query
运行测试,察看结果树
访问/api/user/save没有进行限流
访问/api/user/query进行限流了,每秒发送4个请求,只有两个通过
2. 流控效果
在流控的高级选项中,还有一个流控效果选项
流控效果是指请求达到流控阈值时应该采取的措施,包括三种:
1、快速失败:达到阈值后,新的请求会被立即拒绝并抛出FlowException异常,是默认的处理方式
2、warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常,但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值
3、排队等待:让所有的请求按照先后次序进入到一个队列中进行排队,当某一个请求最大的预期等待时间超过了所设定的超时时间时同样是拒绝并抛出异常
1、warm up
阈值一般是一个微服务能承担的最大QPS,但是一个服务刚刚启动时,一切资源尚未初始化(冷启动),如果直接将QPS跑到最大值,可能导致服务瞬间宕机。
warm up也叫预热模式,是应对服务冷启动的一种方案。阈值会动态变化,从一个较小值逐渐增加到最大阈值。
工作特点:请求阈值初始值是 maxThreshold / coldFactor, 持续指定时长(预热时间)后,逐渐提高到maxThreshold值,而coldFactor的默认值是3。
例如,我设置QPS的maxThreshold为10,预热时间为5秒,那么初始阈值就是 10 / 3 ,也就是3,然后在5秒后逐渐增长到10。
下面我们进行测试
给/api/user/findUserByUserId/{userId}这个资源设置限流,最大QPS为10,利用warm up效果,预热时长为5秒
点下面这个流控
jmeter测试
刚刚启动时,大部分请求失败,成功的只有3个,说明QPS被限定在3
随着时间推移,成功比例越来越高
到sentinel控制台查看实时监控
可以看到是成功的数量在逐步上升,而一开始只有3个成功
2、排队等待
让所有的请求按照先后次序进入到一个队列中进行排队,当某一个请求的等待时间超过了所设定的超时时间时拒绝并抛出异常
例如:QPS = 5,意味着每200 ms处理一个队列中的请求;超时时间timeout = 2000,意味着等待时长超过2000ms的请求会被拒绝并抛出异常。
比如现在一下子来了12 个请求,因为每200ms执行一个请求,那么:
1、第6个请求的等待时长 = 200 * (6 - 1) = 1000ms 可以执行
2、第12个请求的等待时长 = 200 * (12-1) = 2200ms 被拦截
进行测试
给/api/user/findUserByUserId/{userId}这个资源设置限流,最大QPS为10,利用排队的流控效果,超时时长设置为5s
添加流控规则
jmeter测试
QPS为15,超过了我们设定的阈值10
运行测试用例,察看结果树,一开始全部成功,中间慢慢出现失败的结果,最后又全部成功
查看实时监控,开始全部通过,随着响应时间趋近于5秒,开始出现超时的请求,在拦截掉一部分请求之后,后续请求又全部通过
3. 热点参数限流
之前的限流是统计访问某个资源的所有请求,判断是否超过QPS阈值。
而热点参数限流是统计访问某个资源中的不同参数值的请求,判断是否超过QPS阈值。
例如,一个根据id查询商品的接口:
访问/goods/{id}的请求中,id参数值会有变化,热点参数限流会根据参数值分别统计QPS,统计结果:
此时,我们可以认为 id = 1 的这个参数是热点参数,我们可以给它设置一个阈值。当 id = 1的请求触发阈值时被限流,而其他参数的请求可以不受影响
开始测试
案例需求:给/api/user/findUserByUserId/{userId}这个资源添加热点参数限流,规则如下:
1、默认的参数规则是每1秒请求量不超过5
2、给2这个小热点参数设置例外:每1秒请求量不超过10
3、给3这个大热点参数设置例外:每1秒请求量不超过20
注意事项:热点参数限流对默认的spring mvc资源无效,需要利用@SentinelResource注解标记资源
1、标记资源
@SentinelResource("hot")
@GetMapping("/findUserByUserId/{userId}")
public User findUserByUserId(@PathVariable("userId") Long userId){
return userService.findUserByUserId(userId);
}
2、设置热点参数限流规则
在热点规则页面点击新增热点限流规则,不要在簇点链路中直接点击热点,因为没有高级选项
资源名是我们为@SentinelResource注解的value属性设置的值
参数索引,因为我们只有一个参数,所有索引是0
单击阈值,可以理解为默认的阈值,一秒钟只能通过5个请求
参数例外项是配置其他指定的参数值请求的阈值,不使用默认阈值
jmeter测试
写三个请求,参数分别为:1 ,2 ,3,运行测试程序,察看结果树
参数 | ||
1 | 2 | 3 |
![]() | ![]() | ![]() |