整个项目请看gitee:https://gitee.com/xwb1056481167/spring-cloud
sentinel的安装和项目集成:https://blog.csdn.net/www1056481167/article/details/113679945
流控规则
- 资源名: 唯一名称,默认请求路径
- 针对来源: Sentinel可以战队调用者进行限流,填写服务名。默认为default(不区分来源)
- 阈值类型/单击阈值
- QPS(每秒中的请求数量): 当调用该api的QPS达到阈值的时候,进行限流
- 线程数: 当调用该api的线程数达到阈值的时候,进行限流
- 是否集群: 不需要集群
- 流控模式:
- 直连: api达到限流条件时,直接限流
- 关联: 当关联的资源达到阈值的时候,就限流自己
- 链路: 指记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,如果达到阈值,就进行限流)【api级别的针对来源】
- 流控效果:
- 快速失败: 直接失败,抛异常 + Warm Up: 根据codeFactor(冷加载因子,默认为3)的值,从阈值/codeFactor,经过预热时长,才打到设置的QPS的阈值。
- 匀速排队: 匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效。
Sentinel的限流
配置(以下的testA,testB都是项目cloudalibaba-sentinel-service8401的接口)
1、QPS
每秒中的请求次数超过设定的阈值的时候,进行限流
2、线程数
原理: 当调用该api的线程数达到设定的阈值,进行限流
类似于在银行办业务,同一个窗口同一时间只有一个客户在办理,其他客户必须等该客户办理完之后才可以办理
如何演示:
1、设置testB的方法执行时间超过1秒,如下
@GetMapping("/testB")
public String testB() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "-----------testB";
}
2、设置线程数请求阈值
调用该api的方法/testB只支持一个线程,但是连续访问刷新线程数超过1个就报异常
3、关联
当关联的资源达到阈值的时候,就限流自己
eg:当与A关联的资源B达到阈值后,就限流A自己
jmeter下载地址https://archive.apache.org/dist/jmeter/source/#sig
访问:ApacheJMeter.jar测试testB接口,然后此时访问testB接口出现一下结果
4、预热
根据codeFactor(冷加载因子,默认为3)的值,从阈值/codeFactor,经过预热时长,才打到设置的QPS的阈值。
如:秒杀系统开启的瞬间,会有很多流量上来,很有可能会把系统打死,预热方式就是为了把系统保护起来, 可慢慢的吧流量放进来,慢慢的把阈值增加到设定的值
默认的codeFactor为3,即请求QPS从(threshold/3)开始,经过多少预热后才逐渐升至设定的QPS的阈值 案例:阈值10+预热时常设置5秒 系统初始化的阈值为10/3约等于3,即阈值刚开始为3,经过了5秒后阈值才慢慢升高到10
如何测试结果:
刚开始狂点testA,会发现报错Blocked by Sentinel (flow limiting),然后5秒后,阈值从3->10后,会发现狂点刷新浏览器不会出现限流
5、排队等待
让请求以均匀的请求速度通过,阈值类型必须为QPS,否则无效
设定含义/testA每秒1次请求,请超时的话需要排队等待,等待的超时时间为2000毫秒(即2秒)
浏览器一直刷新请求testB(服务被限流)
热点key限流
热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。
比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
1、测试类 @SentinelResource
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
@RequestParam(value = "p2", required = false) String p2) {
return "------------------testHotKey";
}
public String deal_testHotKey(String p1, String p2, BlockException blockException) {
//sentinel 系统默认的提示,Blocked by sentinel (flow limiting)
return "------deal_testHotKey ☹- _ -☹";
}
2、配置热点key接口 资源名必须和@SentinelResource的value相同
特别注意的是,如果设置了热点限流,后端的controller的方法必须有一个blockHandler方法,如果没有,则直接返回错误页面,
原理分析:网页端设置了testHotKey方法的热点限流,然后对应方法也进行了@SentinelResource注解,但是没有指定具体的blockHandler方法,所以当p1传递了参数, 并且在浏览器端的刷新次数达到了一秒钟2次的话,达到了针对testHotKey的热点限流,此时要执行该热点限流指定的blockHandler, 但是却发现没有,此时就会报错误页面的错
参数例外项
参数下标为第0个的参数(后台接收的时候知道是String,需要选择对应的数据类型),正常情况下QPS阈值为1,超过马上被限流,但是如果p1的参数值是5(p1=5)的时候,他的QPS阈值为200。
注意:@SentinelResource处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理。
RuntimeException int a=10/0,这个处理的是java运行时候的异常,走的是RuntimeException,所以此时@SentinelResource不管
@SentinelResource只管配置出错,运行出错走的是异常