所有代码都在github上:https://github.com/demonruin/cloud2020/tree/master
官网地址:https://github.com/alibaba/Sentinel/wiki/热点参数限流
源码位置:com.alibaba.csp.sentinel.slots.block.BlockException
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
这里引入一下主机@SentinelResource 与之前的 @HystrixCommand 功能一样~可以自定义兜底方法等,不再使用默认的兜底结果,限流出问题后,都是用 sentinel系统默认的提示: Blocked by Sentinel( flow limiting)
下面进行热点规则的配置与演示:
1、构建业务测试类,@SentinelResource的value可以随便写,保持唯一性即可,一般是和getmapping的路径一致,然后不写/,blockHandler对应的自定义处理方法要保持参数一致,并加上BlockException参数,然后此时启动项目,访问testHotKey接口是可以的,传p1或者传p2或者都不传或者p1&p2,都是可以的,能正常访问的:
lhttp://localhost:8401/testHotKey?p1=a&p2=b...
@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 exception) {
return "deal_testHotKey!!~~~(* ̄︶ ̄)";// sentinel系统默认的提示: Blocked by Sentinel( flow limiting)
}
2、此时添加sentinel-dashboard的热点规则配置,先进行简单配置:写上资源名、参数索引从0开始,说的是接口接受参数的顺序下标,单机阈值1QPS,统计窗口时长1s。
3、此时单次点击请求带p1参数的请求,能正常响应。等我们频繁刷新,超过1QPS的阈值后,我们再请求,就会触发热点规则,然后出现我们自定义的deal_testHotKey结果,如果不写,就是默认的快速失败结果.经测试只有请求带有参数P1的时候才会触发。
如果我们上述代码中不加 blockHandler = "deal_testHotKey",异常就会打到前台,给你们看下展示效果:
所以,界面太不友好了,我们不建议使用,推荐使用blockHandler = "deal_testHotKey",自定义处理。
参数例外项:
上面讲了热点key的参数限流,第一个参数p1,当QPS超过1秒1次点击后马上被限流,这是普通的案例超过1秒钟一个后,达到阈值1后马上被限流,但是也有参数例外的情况。
当我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样,假如当p1的值等于5时,它的阈值可以达到200,这种参数例外的情况,我们就使用到了热点配置的高级属性,下面配置如图:在原有的热点规则基础上添加了高级属性,即当p1参数类型为String类型,值为5的时候,他的QPS阈值为200。
注意:此处的参数类型只能为 基本类型和String类型。
此时我们设置好热点规则后,我们请求url,当请求:
http://localhost:8401/testHotKey?p1=a时,每秒一次没问题,当超过1QPS的时候,就会出现自定义的页面
http://localhost:8401/testHotKey?p1=5时,每秒一次没问题,狂点刷新也没问题,是因为没有到达200QPS的阈值,不会触发热点规则,此时就表明我们自定义参数例外项配置生效了·~~~~~
表明当p1值为5时,QPS为200阈值,当p1值不为5时,QPS阈值仍为1~~~
附加一个案例:比如说在testHotKey中添加一个int i =10/0,此时运行请求接口,依然会报by zero异常,并展示在前台页面,而不会走我们自定义的处理方法。
所以@SentinelResource管的是sentinel-dashboard中的配置出错,并不会管系统的运行时异常~~~·
@SentinelResource
处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;
RuntimeException
int age = 10/0, 这个是java运行时报出的运行时异常RunTimeException,@SentinelResource不管
总结
@SentinelResource主管配置出错,运行出错该走异常走异常