本篇继续我们的Sentinel,本篇记录一下Sentinel的流量控制,各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
Sentinel官方文档 点此查看
目录
流控规则属性
先看下Sentinel流控规则的添加页面:
一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:
resource
:资源名,即限流规则的作用对象,唯一,默认请求路径。- 针对来源:针对调用者进行限流,填写微服务名,若为
default
则不区分调用来源。- 阈值类型/单机阈值: QPS(每秒钟的请求数量):当调用该resource的QPS达到阈值的时候进行限流。 线程数:当调用该resource的线程数达到阈值的时候进行限流。
- 流控模式: 直接:达到限流条件直接限流。 关联:当关联的资源达到阈值时,就限流自己。 链路:当从入口资源进来的流量达到阈值,就对指定资源进行限流。
- 流控效果: 快速失败:直接失败,抛出异常。 Warm Up:根据codeFactor(冷加载因子,默认为3)的值,从 阈值/codeFactor,经过 设定的预热时长,逐渐到达设置的QPS阈值。 排队等待:匀速排队,让请求以匀速通过,阈值类型必须设置为QPS,否则无效。
另外,同一个资源可以创建多条限流规则。FlowSlot
会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。
流控模式 - 直接失败
默认QPS
配置
如下,我们使用默认阈值类型QPS,单机阈值设置为1,其它也都是默认,此设置的含义为:当每秒钟请求资源/testA的量大于1时,进行限流,直接失败,抛出默认异常Blocked by Sentinel (flow limiting)。
测试
测试一下,浏览器访问 http://localhost:8401/testA 慢慢的点(保证不超过一秒一次)可以正常访问,当快速访问时报如下错误,配置的限流规则生效:
线程数
增加测试方法
在FlowLimitController类中增加以下测试方法。
@GetMapping("/testB")
public String testB() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("------ testB ------");
return "------testB";
}
配置
如下,我们使用阈值类型为线程数,单机阈值设置为1,其它也都是默认,此设置的含义为:当请求资源/testB的线程数大于1时,进行限流,直接失败,抛出默认异常Blocked by Sentinel (flow limiting)。
测试
为测试线程数限流,我们通过TimeUnit.SECONDS.sleep(3)将testB()方法的执行时间拖延3秒,然后使用postman开两个窗口测试,在窗口A请求还没返回结果之前,在窗口B中访问资源/testB,这个时候处理请求B需要额外开启一个线程,此时请求资源/testB的线程数超过阈值,进行限流,直接失败,抛出默认异常Blocked by Sentinel (flow limiting)。
流控模式 - 关联
当关联的资源达到阈值时,就限流自己。
修改测试方法
FlowLimitController类中的测试方法改为如下:
@GetMapping("/testB")
public String testB() {
/*try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
log.info("------ testB ------");
return "------testB";
}
配置
如下,我们配置资源/testA,使用阈值类型为QPS,单机阈值设置为1,流控模式选择关联,使其关联/testB,其它默认,此设置的含义为:当每秒钟请求资源/testB的量大于1时,触发配置的流控规则,对/testA进行限流,直接失败,抛出默认异常Blocked by Sentinel (flow limiting)。
测试
使用postman创建一个线程组,并将 http://localhost:8401/testB 放到线程组中,设置线程组的运行参数,我们开50个线程,每200ms执行一次,如下:
postman运行后,浏览器访问 http://localhost:8401/testA 发现报错如下,说明流控规则生效,当与A关联的资源B达到阈值时,触发了流控规则,限流A的访问 。
流控模式 - 链路
当从入口资源进来的流量达到阈值,就对指定资源进行限流,即:当从某个接口过来的资源达到限流条件时,开启限流,它的功能有点类似于针对来源配置项,针对来源针对的是微服务,比如有两个微服务A和B,都有共同的资源/testA,链路针对的是微服务中的接口,即他们的区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度更细。
流控效果 - 快速失败
默认的流控效果就是快速失败,如上面那些测试,如果触发限流规则,直接立刻抛出默认异常Blocked by Sentinel (flow limiting)。
流控效果 - Warm Up(预热)
Warm Up方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
它会根据codeFactor(冷加载因子,默认为3)的值,从 阈值/codeFactor,经过设定的预热时长,逐渐到达设置的QPS阈值。
配置
如下,我们配置资源/testB,使用阈值类型为QPS,单机阈值设置为5,流控效果选择Warm Up,其它默认,此设置的含义为:开始只能每秒接受 5/codeFactor个请求,经过设定的预热时长(5秒),逐渐到达设置的QPS阈值5,效果为:开始访问 http://localhost:8401/testB 时每秒请求别超过5/3个才能正常访问,5秒后可以接受的请求可以达到每秒5次。
测试
使用浏览器手动测试,快速访问 http://localhost:8401/testB ,开始可以接受5/codeFactor个请求,即每秒不到两个,我们每次快速访问三次,开始前5秒会报错,5秒后,发现不再报错了,从浏览器效果可以看出,另外从管理界面的实时监控中可以看出,如下:
通常用于秒杀系统中,秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。
流控效果 - 排队等待
匀速排队方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法,阈值类型必须设置为QPS,否则无效。
配置
如下,我们配置资源/testB,使用阈值类型为QPS,单机阈值设置为2,流控效果选择排队等待,超时时间设置为20000ms(20秒),其它默认,此设置的含义为:代表一秒匀速的通过 2 个请求,也就是每个请求平均间隔恒定为 1000 / 2 = 500 ms
,每一个请求的最长等待时间为20s。
测试
使用postman创建一个线程组,并将 http://localhost:8401/testB 放到线程组中,设置线程组的运行参数,我们开10个线程,每200ms执行一次,从控制台打印的效果看,大约每0.5秒即500ms打印一次,即每500ms才放过一个请求,并不是200ms一次请求,说明配置生效,控制台打印效果如下:
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
注意:匀速排队模式暂时不支持 QPS > 1000 的场景。