李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
03.Sentinel流控规则
Leefs
2023-01-14 PM
641℃
0条
[TOC] ### 一、概述 流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。 + 流量限制控制规则,分为:**流控模式**和**流控效果**  **各选项含义**: + **资源名**:唯一名称,默认请求路径 + **针对来源**:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源) + **阈值类型/单机阈值**: + **QPS(每秒钟的请求数量)**:当调用该API的QPS达到阈值的时候,进行限流 + **线程数**:当调用该API的线程数量达到阈值的时候,进行限流 + **是否集群**:当前不需要集群 + **流控模式**: + **直接**:API达到限流条件时,直接限流 + **关联**:当关联的资源达到阈值时,就限流自己 + **链路**:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)(API级别的针对来源) + **流控效果**: + **快速失败**:直接失败,抛异常 + **Wam Up**:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFacotor,经过预热时长,才达到设置的QPS阈值 + **排队等待**:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效 ### 二、流控模式 **流控模式有三种**: - **直接**:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式 - **关联**:统计与当前资源相关的另一个资源,当关联的资源触发阈值时,对当前资源限流 - **链路**:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流  #### 2.1 直接(默认)+快速失败(默认) **(1)QPS直接快速失败** + **QPS**:`query per second`,**每秒钟的请求数量**,当调用该api的QPS达到阈值时,进行限流。 > 模拟场景:当一秒内如果接口`/testA`的请求数量大于1,就会抛出异常。即:`QPS`>1,就直接-快速失败,报默认错误  + 查看列表记录  + **测试** 当/testA的访问超过1次/s时,页面报错  当访问量QPS<=1时,可以继续正常访问。 直接调用默认的报错信息在技术上是OK的,但是是否应该有自定义的后续处理? 应该有类似`Hystrix`的`fallback`的兜底方法。 **(2)线程数直接快速失败** + 当调用该api的线程数达到阈值的时候,进行限流。 与QPS直接快速失败不同的是,QPS情况下限制的是流量,比如银行的人流量只能是1人/s,也就是说每次只能一个人进入银行办理业务;而线程数就好比银行只有一个窗口开放,一群人都可以进入银行,但是每次只能处理一个人的业务。 > 模拟场景:当有两个及以上的线程同时请求`\testA`接口时,就会抛出异常。即:当并发线程数大于1时,后面访问的线程会直接快速失败,抛出默认异常。 + Sentinel控制台配置  + 修改sentinel-service-demo01服务业务类 ```java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; @RestController public class FlowLimitController { @GetMapping("/testA") public String testA() { //暂停0.8秒 try { TimeUnit.MILLISECONDS.sleep(800); } catch (InterruptedException e) { throw new RuntimeException(e); } return "------testA"; } @GetMapping("/testB") public String testB() { return "------testB"; } } ``` 修改完成后重启服务 + 测试浏览器访问`/testA`接口  #### 2.2 关联 + 当关联的资源达到阈值时,就限流自己。 + 比如当与A关联的资源B达到阈值后,就限流A自己。 + 支付接口达到阈值,限流下订单的接口。 **(1)Sentinel控制台配置** > 模拟场景:当关联资源/testB的QPS阀值超过1时,就限流/testA的访问地址,即:当关联资源到阈值后限制配置好的资源名。  **(2)通过postman访问接口测试** + **通过postman单独访问`/testB`接口**  + **postman模拟并发密集访问/testB** 1、先创建一个集合,名字自己随便取。  2、将创建的访问`/testB`的请求保存在创建的集合中  3、设定集合运行参数 > 设置条件:20个线程,每次间隔0.3s访问一次(QPS>1)  **(3)再访问/testA**  发现被限流,f访问失败,等postman执行完毕,testA又可以访问了。 #### 2.3 链路 + 需要测试链路的话,`spring-cloud-alibaba-dependencies`版本需要`2.1.1.RELEASE`以上; 如果修改版本时,需要在父工程的pom中修改,不要直接在子module的pom中修改,版本有对应关系,不然报错。 + Sentinel从1.6.3版本开始,Sentinel Web Filter 默认收敛所有的URL入口的Context,因此链路限流不生效。 + 1.7.0版本开始,官方在CommomFilter中引入了`WEB_CONTEXT_UNIFY`这个init parameter,用于控制是否收敛context,将其配置为`false`即可根据不同的URL进行链路限流。  **链路模式:只针对从指定链路访问到本资源的请求做统计,判断是否超过阈值。** > 例如有两条请求链路: > > + /testA -> /common > + /testB -> /common > > 如果只希望统计从/testB进入到/common的请求,则可以这样配置  ### 三、流控效果 **快速失败**在上面的流控模式演示过了,他是默认的流控效果,直接失败,抛出异常。 #### 3.1 warm up 预热 *官网地址:[限流 冷启动](https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81---%E5%86%B7%E5%90%AF%E5%8A%A8)* 公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值 当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。 这个场景主要用于启动需要额外开销的场景,例如建立数据库连接等。 通常冷启动的过程系统允许通过的 QPS 曲线如下图所示:  默认 `coldFactor` 为 3,即请求 QPS 从 `threshold / 3` 开始,经预热时长逐渐升至设定的 QPS 阈值。 > 案例:阈值为10+预热时长设置5秒。 系统初始化的阈值为10/3约等于3,即阈值刚开始为3;然后过了5秒后阈值才慢慢升高恢复到10。  **测试**  狂点请求,可以看通过的QPS逐渐增加,最开始会报错限流,之后就可以扛住`10/s`的QPS了。 应用场景:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。 #### 3.2 排队等待 *官网地址:[匀速排队](https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6)* 匀速排队(`RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER`)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。 该方式的作用如下图所示:  这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。 > 注意:匀速排队模式暂时不支持 QPS > 1000 的场景。 匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。 > 模拟场景:/testB的QPS最大为1,超过的话就排队等待,等待的超时时间为`20000ms`。 + **Sentinel控制台配置**  + **修改业务代码,将线程名打印出来以验证是否排队** ```java @RestController @Slf4j public class FlowLimitController { @GetMapping("/testA") public String testA() { //暂停0.8秒 /*try { TimeUnit.MILLISECONDS.sleep(800); } catch (InterruptedException e) { throw new RuntimeException(e); }*/ return "------testA"; } @GetMapping("/testB") public String testB() { log.info(Thread.currentThread().getName() + "\t"); return "------testB"; } } ``` + **postman测试**  可以通过服务控制台输出结果来查看请求是否排队。
标签:
SpringCloudAlibaba
,
Sentinel
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/2802.html
上一篇
02.Sentinel初始化演示工程
下一篇
04.Sentinel降级规则
取消回复
评论啦~
提交评论
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
40
标签云
Java阻塞队列
散列
Elasticsearch
高并发
Python
容器深入研究
Http
Jquery
Eclipse
Flink
Yarn
DataWarehouse
MySQL
Java
RSA加解密
微服务
CentOS
机器学习
Spark
数学
Stream流
Java编程思想
递归
LeetCode刷题
DataX
字符串
VUE
Filter
FastDFS
BurpSuite
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞