一、Sentinel 流控规则基本介绍
1、Snetinel 流控规则配置方式
Sentinel 支持可视化的流控规则配置,使用非常简单;可以在监控服务下的“簇点链路” 或
“流控规则” 中 给指定的请求资源配置流控规则;一般推荐在 “簇点链路” 中配置流控规则。
如下图所示:
1)在 “簇点链路” 中配置流控规则
2)在 “流控规则” 中配置流控规则
2、流控规则名词解析
1)资源名:唯一名称,默认请求路径
2)针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
3)阈值类型:
QPS:每秒钟的请求数量,当调用该API的QPS达到阈值的时候,进行限流
并发请求数:每秒调用请求的线程数量,当调用该API的线程数量达到阈值的时候,
进行限流
4)单机阈值:指每秒调用当前资源的次数
5)是否集群:当前不需要集群,先不测试集群
6)流控模式:
I)直接:API达到限流条件时,直接限流
II)关联:当关联的资源达到阈值时,就限流自己
III)链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,
就进行限流)(API级别的针对来源)
7)流控效果:
I)直接失败:直接失败,抛出异常
II)Wam Up:根据codeFactor(冷加载因子,默认3)的值,从“阈值/codeFacotor” 开始,
经过预热时长,才达到设置的QPS阈值
III)排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效
二、具体的流控规则配置练习
1、准备环境
创建服务(sentinel-8401),并整合Sentinel(具体步骤请参考上一篇“整合Sentinel”);
在 sentinel-8401,创建controller类 FlowlimitController,定义2个资源 “/testA”、“/testB”;
如下所示:
@RestController
public class FlowlimitController {
@GetMapping("/testA")
public String testA() {
return "testA------测试";
}
@GetMapping("/testB")
public String testB(){
return "testB------测试";
}
}
1、直接
1.1、QPS(阈值类型)+直接(流控模式)
给请求testA配置流控,阈值类型选择 “QPS”,单机阈值配置为 1,流控模式选择“直接”,
流控效果选择“直接失败”表示当请求/testA每秒请求数超过1时,请求直接失败;
如下图所示:
然后在浏览器或PostMan 中快速访问 “/testA”,当达到限流上限后的请求直接返回异常,
如下所示:
流控模式为 “直接” 、流控效果为“直接”失败的方式很简单,就测试一种情况就行了
2、关联
官方解释:当关联的资源达到阈值时,就限流自己。
通俗解释来说,比如那我们的程序,现在有testA接口和testB接口,当A关联的资源B达到
阈值后,就限流自己,也就是B到达阈值,限流A本身,B本身不会被限流。
换到程序里面来说比如一个电商系统中,支付系统达到阈值,就限流下订单系统。
如下图所示:
2.1、“关联”使用步骤
1)准备2个请求资源“testA接口和testB接口”,如下所示:
@RestController
public class FlowlimitController {
@GetMapping("/testA")
public String testA() {
return "testA------测试";
}
@GetMapping("/testB")
public String testB(){
return "testB------测试";
}
}
2)给请求资源 “testA” 添加流控规则,testA 关联 testB,并配置testB的QPS为1
如下所示:
3)测试
先在浏览器或postman访问testB,达到限流上限,然后再访问testA,
testA 也会被限流,直接返回失败;
注意:此时testB并没有被限流,testB还能正常访问
3、链路
链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流,它的功能有
点类似于“针对来源”配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对
上级接口,也就是说它的粒度更细。
比如在一个微服务中,两个接口都调用了同一个Service中的方法,并且该方法用
SentinelResource(用于定义资源)注解标注了,然后对该注解标注的资源(方法)进
行配置,则可以选择链路模式。如下图所示:
此时若访问testA时史资源 common 达到了限流上限,再访问testA时会直接抛出异常
(testA被限流了),但此时testB 正常访问,testB没有被限流。
3.2、测试步骤
1)准备service接口common
public interface SentinelService {
String common();
}
/****************************************************
* 测试 Sentinel 流控规则--链路
* 链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流,它的功能有点类似于针对来源配置项,
* 与来源项的区别在于:来源项针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度更细。
* 比如在一个微服务中,两个接口都调用了同一个Service中的方法,并且该方法用SentinelResource(用于定义资源)注解标注了,
* 然后对该注解标注的资源(方法)进行配置,则可以选择链路模式。
*
* @author
* @date 2025/6/23 10:29
****************************************************/
@Service
public class SentinelServiceImpl implements SentinelService {
/**
* 注解 @SentinelResource 指定需要限流的资源(方法)
* @return
*/
@SentinelResource("common")
@Override
public String common() {
return "common";
}
}
2)修改FlowlimitController 中的testA 与testB 方法,并调用方法common
@RestController
public class FlowlimitController {
@Autowired
private SentinelService sentinelService;
@GetMapping("/testA")
public String testA() {
return sentinelService.common();
}
@GetMapping("/testB")
public String testB(){
return sentinelService.common();
}
}
3)给testA 链路中的方法资源common 配置流控规则,如下所示:
4)修改配置文件application.yml,在Sentinel 配置中添加配置项web-context-unify=false;
将 CommonFilter 中的参数 WEB_CONTEXT_UNIFY 设置为false,即可根据不同的URL
开启限流,否则不生效,配置内容如下:
5)测试结果:
三、具体流控效果配置练习
1、Wam Up
Warm Up方式,即预热/冷启动方式。
该方式主要用于系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位
可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值
上限,给冷系统一个预热的时间,避免冷系统被压垮的情况。
预热公式:预热时间 = 阈值/coldFactor(coldFactor:冷加载因子,默认值为3);
经过预热时间后才会达到阈值,即启动的过程系统允许通过的QPS不会瞬间到达阈值,
会慢慢的上升到QPS阈值,
冷启动的过程系统允许通过的QPS曲线如下图:
使用场景:一般秒杀系统中会有这样的流控设置,为了防止秒杀瞬间造成系统崩溃。
1.1、Wam Up使用示例
默认冷加载因子coldFactor为3,当发起请求即请求QPS从(阈值/3)开始(即第一次请求的
初始化阈值= 当前阈值/coldFactor),经过指定预热时长才逐步升至设定的QPS阈值,
如:当前阈值设置为10,预热时长设置为5秒,那么系统 初始化时阈值 = 当前阈值10/3
约等于3,即阈值在此时为3,经过5秒后阈值才慢慢升高到10
流控规则配置如下:
测试:
直接在浏览器上手动刷新,然后我们来看Sentinel的实时监控中QPS的变化,
如下图所示:
通过Sentinel的实时监控的图中请求QPS的变化可以发现若每秒的QPS大于
初始化阈值(当前阈值/coldFactor),那么多于的请求会被拒绝,在浏览器中也可以
发现有请求返回:Blocked by Sentinel (flow limiting)
如下图所示:
2、排队等待
2.1、概念
排队等待方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应
的是漏桶算法。
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒
有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期
间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求(削峰填谷)。如下图所示:
匀速器
它的中心思想是,以固定的间隔时间让请求通过。当请求到来的时候,如果当前请求距
离上个通过的请求通过的时间间隔不小于预设值,则让当前请求通过。否则,计算当前
请求的预期通过时间,如果该请求的预期通过时间小于规则预设的 timeout 时间,则该请
求会等待直到预设时间到来通过(排队等待处理);若预期的通过时间超出最大排队时
长,则直接拒接这个请求。如下图所示:
Sentinel 匀速排队等待策略是漏桶算法结合虚拟队列等待机制实现的。
注意:排队等待(匀速排队)模式暂时不支持 QPS > 1000 的场景。
2.2、示例
给请求“/testF” 配置 “排队等待” 流控效果;配置QPS的单机阈值为1,表示1秒只处理一个
请求,超时时间(最大排队时间)为2000(20秒,单位是毫秒);当1s内进来25个请求,
第一个请求会被立即处理,后续的请求被放到等待队列中,队列中的请求只要在超时时间
之内,都可以被处理,超过了超时时间就被直接拒绝了。流控规则配置如下:
注意:若想看到被拒绝的场景,可以把超时时间调小点,然后在浏览器中快速刷新请求;
postman是每秒发送一次请求,测不出超时拒绝的场景
然后在FlowlimitController 类中的 testF 方法中打印一条输出语句,如下图所示:
最后我们可以通过Postman来进行测试,发送请求时没有延迟,同时发送25条请求,
然后我们会发现就是排队效果1秒执行一个请求,同时我们在Idea中也可以看到打印效果,
也是1s输出1条。
如下图所示: