李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
05.Sentinel热点key限流和系统规则
Leefs
2023-01-17 PM
1923℃
0条
[TOC] ### 一、概述 *官网地址:[热点参数限流](https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81)* **何为热点?** 热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的Top K数据,并对其访问进行限制。 比如: - 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制 - 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制 热点参数限制会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限制。 热点参数限流可以看作是一种特殊的流量控制,仅对包含热点参数的资源调用生效。 ![05.Sentinel热点key限流01.png](https://lilinchao.com/usr/uploads/2023/01/3076389145.png) Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。 ### 二、热点参数规则 热点参数规则(`ParamFlowRule`)类似于流量控制规则(`FlowRule`): | 属性 | 说明 | 默认值 | | ----------------- | ------------------------------------------------------------ | -------- | | resource | 资源名,必填 | | | count | 限流阈值,必填 | | | grade | 限流模式 | QPS 模式 | | durationInSec | 统计窗口时间长度(单位为秒),1.6.0 版本开始支持 | 1s | | controlBehavior | 流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持 | 快速失败 | | maxQueueingTimeMs | 最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持 | 0ms | | paramIdx | 热点参数的索引,必填,对应 `SphU.entry(xxx, args)` 中的参数索引位置 | | | paramFlowItemList | 参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 `count` 阈值的限制。**仅支持基本类型和字符串类型** | | | clusterMode | 是否是集群参数流控规则 | `false` | | clusterConfig | 集群流控相关配置 | | **兜底方法** 兜底方法分为两种:**系统默认**和**客户自定义** 根据之前的案例,都是使用sentinel系统默认的提示:Blocked by Sentinel (flow limiting)。 **那我们能不能自定义兜底方法呢?类似hystrix,某个方法出问题了,就找对应的兜底降级方法?** 类似于**@HystrixCommand,** 引入**@SentinelResource**注解。 ### 三、测试案例 #### 3.1 业务类方法 在服务`sentinel-service-demo01`的业务类中增加如下热点测试方法 ```java @GetMapping("/testHotKey") @SentinelResource(value = "testHotKey", blockHandler = "del_testHotKey") //这里的名称可以随便写,但是一般跟rest地址一样 public String testHotkey(@RequestParam(value = "p1", required = false) String p1, @RequestParam(value = "p1", required = false) String p2) { return "------testHotkey"; } //这里是我们自定义的兜底方法,BlockException不要打成了BlockedException public String del_testHotKey(String p1, String p2, BlockException e) { return "这次不用默认的兜底提示Blocked by Sentinel(flow limiting),自定义提示:del_testHotKeyo(╥﹏╥)o..."; } ``` > 注解`@SentinelResource(value = "testHotKey", blockHandler = "del_testHotKey")` 说明 + `value = "testHotKey"`:是一个标识(Sentinel资源名),与rest的`/testHotKey`对应,这里value的值可以任意写,但是一般约定与rest地址一致,唯一区别是没有`/`。 + `blockHandler = "del_testHotKey"`:则表示如果违背了Sentinel中配置的流控规则,就会调用我们自己的兜底方法`del_testHotKey` #### 3.2 配置热点key限流规则 > 绑定testHotKey资源,把testHotKey对应的第一个参数作为热点key进行监控。 > > **设定热点限流规则**:当该资源的访问QPS超过1次/s的时候,产生限流并执行自定义的del_testHotKey兜底方法 > > **简而言之**:方法testHotKey里面第一个参数只要QPS超过每秒1次,马上降级处理。 需要访问一次`http://localhost:8401/testHotKey?p1=1`的控制器接口,然后才会在Sentinel中显示出簇点链路。 根据上面的控制器指定的请求参数,索引为0的参数是p1,所以只要请求的路径中有p1这个请求参数都会被设置的规则进行限流,限流的就会执行兜底放法。 ![05.Sentinel热点key限流02.png](https://lilinchao.com/usr/uploads/2023/01/1180615515.png) #### 3.3 测试 **(1)访问如下地址** ``` http://localhost:8401/testHotKey?p1=a&p2=b ``` 如果每秒一次进行访问,则可以正常显示,如果访问次数每秒超过一次,则会触发热点限流,执行自定义兜底方法。 ![05.Sentinel热点key限流03.jpg](https://lilinchao.com/usr/uploads/2023/01/3663721121.jpg) **(2)如果去掉参数p1,仅传入参数p2** ![05.Sentinel热点key限流04.jpg](https://lilinchao.com/usr/uploads/2023/01/3490043771.jpg) 不管我们点击多快都没有影响,并没有触发热点限流。 **(3)现在开两个访问** + 通过jmeter压测 ``` http://localhost:8401/testHotKey?p1=a&p2=b ``` ![05.Sentinel热点key限流05.jpg](https://lilinchao.com/usr/uploads/2023/01/1919909638.jpg) + 再单独使用浏览器访问`http://localhost:8401/testHotKey?p2=b` ![05.Sentinel热点key限流06.jpg](https://lilinchao.com/usr/uploads/2023/01/2678387863.jpg) 发现只带参数p2访问没有任何影响。 **(4)不配置blockeHandler(兜底方法)** ```java @GetMapping("/testHotKey") @SentinelResource(value = "testHotKey") //这里的名称可以随便写,但是一般跟rest地址一样 public String testHotkey(@RequestParam(value = "p1", required = false) String p1, @RequestParam(value = "p1", required = false) String p2) { return "------testHotkey"; } ``` 触发热点限流降级会出现error page,对用户不友好。 #### 3.4 参数例外项 上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流 > 参数例外项:指定参数的具体值是什么,以及对该参数的阈值是多少,例如索引为0的参数`p1=5`那么久符合了参数值是5,那他的限流阈值就可以达到一秒钟QPS 200个的请求,如果参数不是5,那么p1的请求限制QPS就是一秒钟一个 > > 字面理解:我对该项配置的理解就是,针对传入参数的特定值进行单独设置阈值。以达到对传入的参数值进行精准控制。 **需求** > 当p1=5时,QPS达到200才限流降级 ![05.Sentinel热点key限流07.jpg](https://lilinchao.com/usr/uploads/2023/01/3366777361.jpg) 最后点击绿色【添加】按钮。 **测试** 通过浏览器访问如下地址,即使点击在快也没有限流。 ``` http://localhost:8401/testHotKey?p1=5&p2=b ``` ![05.Sentinel热点key限流08.jpg](https://lilinchao.com/usr/uploads/2023/01/2176786172.jpg) > 注意:@SentinelResource只对触发Sentinel配置项产生的异常进行兜底,不管Java运行异常 ### 四、系统规则(系统自适应限流) #### 4.1 概述 系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。 系统保护规则是应用整体维度的,而不是资源维度的,并且**仅对入口流量生效**。入口流量指的是进入应用的流量(`EntryType.IN`),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。 #### 4.2 系统规则 **系统规则支持以下的模式**: - **Load 自适应**(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 `maxQps * minRt` 估算得出。设定参考值一般是 `CPU cores * 2.5`。 - **CPU usage**(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。 - **平均 RT**:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。 - **并发线程数**:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。 - **入口 QPS**:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。 #### 4.3 案例 > 配置全局QPS:系统中的所有接口QPS不能大于1 ![05.Sentinel热点key限流09.jpg](https://lilinchao.com/usr/uploads/2023/01/1944532338.jpg) 不管是/testA还是/testB 只要QPS > 1 整个系统就不能用。 这个粒度太粗,就相当于一个窗口人很多,整个银行就不接待人了,不太建议使用。
标签:
SpringCloudAlibaba
,
Sentinel
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/2827.html
上一篇
04.Sentinel降级规则
下一篇
IDEA编译运行Spark源码
取消回复
评论啦~
提交评论
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
43
标签云
Zookeeper
HDFS
Golang基础
二叉树
序列化和反序列化
Livy
机器学习
Python
Spark
Flume
Java阻塞队列
RSA加解密
nginx
CentOS
SQL练习题
Sentinel
查找
JavaScript
Kibana
MyBatisX
Hive
Azkaban
Ubuntu
线程池
FileBeat
工具
递归
Nacos
JavaWeb
Spring
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞