李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
03.Sentinel流控规则
Leefs
2023-01-14 PM
3569℃
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
工具
35
其它
25
GO
48
NLP
8
标签云
高并发
SpringCloud
BurpSuite
Jenkins
字符串
Ubuntu
Flink
Kafka
哈希表
链表
稀疏数组
Redis
Golang
Scala
Http
Spark Streaming
Filter
散列
序列化和反序列化
查找
SpringBoot
国产数据库改造
栈
并发编程
SpringCloudAlibaba
Quartz
Spark RDD
微服务
FileBeat
Netty
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞