写点什么

SpringCloud 从入门到精通 16---Sentinel 流控

用户头像
Felix
关注
发布于: 2021 年 02 月 02 日

上节中,我们已经搭建了sentinelweb管理界面,并且cloud-sentinel-service-8010已经被sentinel监控了起来,接下来,我们通过几个简单的例子,来了解下sentinel常见的限流方式

阈值流控

QPS 限流

顾名思义,QPS 限流对于接口的访问进行限制,当访问的频率高于我们限制的频率之后,对接口进行限流,现在我们有两个接口/testA/testB,正常访问的情况下,两个接口都可以正常的返回数据,接下来,我们对接口/testA进行 QPS限流,当访问频次超过1时,进行限流

我们在簇点链路下,点击列表视图,然后选中/testA流控,这里我们直接针对/testA接口进行阈值类型为 QQPSQ 的限流,单机阈值设置为1,流控模式流控效果均保持默认

这样,我们就创建了一个针对/testA接口的QPS限流,当QPS大于1的话,就会快速失败

接下来,尝试访问http://localhost:8010/testA

结果正常,然后,快速刷新界面,使得对于接口/testAQPS大于1,就会出现如下的信息

QPS大于1的时候,就会被我们设置的QPS 限流进行限流,并返回对应的限流信息

线程限流

线程限流也就是限制当前接口处理的线程数,我们新增一个接口/testC

package com.felix.sentinel.controller;
import com.felix.common.result.CommonResult;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestControllerpublic class LimitingController { @GetMapping(value = "/testA") public CommonResult testA(){ return CommonResult.success("TEST A"); }
@GetMapping(value = "/testB") public CommonResult testB(){ return CommonResult.success("TEST B"); }
@GetMapping(value = "/testC") public CommonResult testC(){ try { TimeUnit.SECONDS.sleep(5); return CommonResult.success("TEST C"); } catch (InterruptedException e) { return CommonResult.success("TEST C TIME OUT"); } }}
复制代码

接口/testC中,使线程进行5S的休眠,已保证在5S内,我们可以让另一个客户端进行请求,从而触发限流效果.首先给接口/testC增加线程限流

此时流控规则如下图

这时,先打开浏览器访问http://localhost:8010/testC,在浏览器加载的过程中也就是 5S 内,打开新的窗口访问http://localhost:8010/testC即可触发线程限流,由于浏览器缓存的原因,测试此项存在问题,所以我采用postman来测试

正常请求结果

触发限流后的结果

流控模式

关联流控

举例来讲,当我们访问/testA接口的时候,/testA接口依赖于/testC接口的逻辑,那么假如/testC接口触发了限流的策略,也就是/testC无法提供业务服务的时候,与之关联的/testA接口也同样会被限流.

我们针对/testA新建一个流控规则

这里/testA的流控模式采用关联模式,关联资源为/testC,也就是当/testC触发了限流规则后,/testA也同样会由于关联了/testC从而触发限流

我们先访问http://localhost:8010/testC,触发5S的线程等待,在此期间访问http://localhost:8010/testA,查看结果

/testC整处于业务处理中的时候

/testA将会被限流

等到/testC业务处理完毕之后,/testA的响应进入正常状态

链路流控

在各个微服务中,微服务间的调用错综复杂,比如/testA调用了/testC,/testD调用了/testC,/testE调用了/testA同时/testA又调用了/testC(/testE间接调用了/testC),假如我想针对所有对于/testC的直接/间接调用进行流控,那么就需要采用链路流控.

首先删除刚才新增的对于/testC接口的流控规则,然后新建一个流控规则


这里流控模式选择链路,入口资源为接口/testC所在的资源下

这样,当我们无论直接/间接调用/testC,都会触发此限流.大家可以创建一个新的服务cloud-sentinel-service-8011,采用openFeign进行进行微服务的调用

我这里通过8011端口的/testD接口访问/testC,在5S内,如果重复访问了/testD,那么就会触发限流规则,接口/testD返回信息如下

再看控制台输出,其实就是触发了限流

流控效果

快速失败

顾名思义,当触发了流控规则之后,直接返回限流信息给客户端,这也是我们之前一直采用的模式,这里就不再进行详细示例了

预热

预热的目的,就是给系统一个缓冲的时间,防止突发流量/冷启动时造成系统崩溃.官方描述如下

当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。

QPS限流来讲,我们可以对初始的QPS进行限流,随着时间的增长(给定的预热时间),让QPS达到正常的水平,接下来对/testA接口进行预热

上面的规则,表示当系统启动后,/testA接口的初始QPS10 / 3 = 3(冷启动因子固定为 3),随着时间的增长,10S后,QPS的阈值就变成了 10,这里我们可以通过快速多次访问http://localhost:8010/testA查看结果,会发现刚开始可能会有

但是 10S过后,快速访问http://localhost:8010/testA都不再会出现限流信息了,因为此时QPS 限流的阈值已经变成了 10

排队等待

字面上很容易理解,当过来多个请求后,不再直接进行限流,而是采用排队的形式,依次处理请求,客户端可以等待结果返回,也可以重新发起新的请求,这种流控主要是削峰填谷.需要注意的是,此流控只针对QPS限流有用

我们针对/testA新建一个流控规则,限制QPS阈值为1,超时时间为60S


这里我们使用jmeter模拟 20 个线程,同时发起请求访问/testA

可见,线程都在17:21:31进行了创建,按时结果数据是每秒返回一个,也就是我们限流策略中设置的每秒处理1个请求,其他的请求都进行排队处理

发布于: 2021 年 02 月 02 日阅读数: 27
用户头像

Felix

关注

还未添加个人签名 2020.12.24 加入

还未添加个人简介

评论

发布
暂无评论
SpringCloud 从入门到精通16---Sentinel流控