Sentinel.02.Sentinel之流量控制

Posted 潮汐先生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sentinel.02.Sentinel之流量控制相关的知识,希望对你有一定的参考价值。

前言

在上一节中我们知道Sentinel 支持以下几种规则:流量控制规则熔断降级规则系统保护规则来源访问控制规则热点参数规则

Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。同时 Sentinel 也提供相关 API,供您来定制自己的规则策略

本篇文章我们来看一下Sentinel的流量控制规则

概述

定义

**流量控制(Flow Control)**其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

限流的直接表现是在执行流控的时候抛出 FlowException 异常。FlowExceptionBlockException 的子类,我们可以捕捉 BlockException 来自定义被限流之后的处理逻辑。

同一个资源可以对应多条限流规则。FlowSlot 会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。

规则 (FlowRule)

一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果。

Field说明默认值
resource资源名,资源名是限流规则的作用对象
count限流阈值
grade限流阈值类型,QPS 或线程数模式QPS 模式
limitApp流控针对的调用来源default,代表不区分调用来源
strategy调用关系限流策略:直接、链路、关联根据资源本身(直接)
controlBehavior流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流直接拒绝

流量控制主要有两种统计类型,一种是统计线程数,另外一种则是统计 QPS。类型由 grade 字段来定义。

基于QPS/并发数的流量控制

小试牛刀

新增规则

簇点链路

打开我们的Sentinel DashBoard界面,在侧边栏菜单的簇点链路中找到我们需要流控的资源,我们这里是/test/hello,点击后面的+流控按钮,即可打开新增流控规则的界面。如下图所示

在新增流控规则的窗口中我们直接展开高级选项(这里暂时不讨论集群方式),如下图所示:

流控规则

我们也可以在流控规则菜单中点击新增流控规则,只不过这种方式弹出的新增窗口的资源名要自己指定

流控测试

我们这里先做一个简单的流控测试,我们将单机阈值直接设置为1,其余保持默认;按照这样的配置如果一秒内的请求数大于1那么资源就会被直接流控,抛出Blocked by Sentinel (flow limiting)异常。如下图所示:

并发线程数流量控制

线程数限流用于保护业务线程数不被耗尽。例如,当应用所依赖的下游应用由于某种原因导致服务不稳定、响应延迟增加,对于调用者来说,意味着吞吐量下降和更多的线程数占用,极端情况下甚至导致线程池耗尽。为应对高线程占用的情况,业内有使用隔离的方案,比如通过不同业务逻辑使用不同线程池来隔离业务自身之间的资源争抢(线程池隔离),或者使用信号量来控制同时请求的个数(信号量隔离)。这种隔离方案虽然能够控制线程数量,但无法控制请求排队时间。当请求过多时排队也是无益的,直接拒绝能够迅速降低系统压力。Sentinel线程数限流不负责创建和管理线程池,而是简单统计当前请求上下文的线程个数,如果超出阈值,新的请求会被立即拒绝。

小试牛刀

新增规则

我们直接打开新增流控规则窗口,阈值类型选择并发线程数,单机阈值设置为2。如下图所示:

流控测试

并发线程数测试我们需要使用JMeter来模拟线程进行压力测试,有关JMeter的使用可以参考文章压力测试工具JMeter的简单使用

新建线程组

我们新建一个线程组,在启动的时候同时发送10个请求,如下所示:

新建http请求

启动测试

我们点击菜单栏上方绿色的启动按钮启动测试,在结果树中查看执行结果,如下图所示:

流控模式

新增流控规则界面的高级选项中有一项流控模式可供选择,分别是直接关联链路(后期专门介绍链路,本文不具体展开)

直接模式

当配置资源在运行过程中超过当前规则配置的阈值之后对该资源请求做相应的流控效果。上面基于QPA/并发数的流量控制并发线程数流量控制中的小试牛刀就是基于这种方式处理的

关联模式

当配置资源在运行过程中超过当前配置规则配置的阈值之后对他所关联的资源请求做相应的流控效果。对于该迷失的效果请看下面的实例

TestController.java

我们修改TestController.java,在里面我们新增方法sayBye(),然后重启系统。如下图所示:

/**
 * @Author Christy
 * @Date 2021/8/6 10:17
 **/
@RestController
@RequestMapping("/test")
public class TestController {
    private static final Logger log = LoggerFactory.getLogger(TestController.class);

    @RequestMapping("/hello")
    public String sayHello(){
        log.info("Hello, Sentinel!");
        return "Hello, Sentinel!";
    }

    @RequestMapping("/bye")
    public String sayBye(){
        log.info("Bye, Sentinel!");
        return "Bye, Sentinel!";
    }
}

新增规则

我们修改前面的柜子,流控模式选择关联,关联资源写/test/bye,流控效果(后面讲)暂时选快速失败

测试

我们修改JMeter中的线程组,设置循环每秒钟发送10个请求,如下图所示:

修改http请求路径为/test/bye,如下图所示:

启动JMeter测试,结果如下所示:

从图中我们可以看到对于关联资源/test/bye可以正常访问,但是对于资源/test/hello却被限流了,所以对于关联模式这是一种反向流控:当被关联资源达到阈值,会对资源进行流控

链路模式

当配置资源在运行过程中超过当前配置规则的阈值后对链路中的资源直接抛出失败。这种模式在后面我们单独拿出来讲,这里先忽略。

流控效果

流控效果选项只是针对QPS来说的,如果我们将阈值类型选择并发线程数的话可以看到是没有流控效果这一选项的

  • 直接拒绝:(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)是默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。
  • Warm Up:(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。–官网
  • 匀速排队:(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,只能对请求进行排队等待,对应的是漏桶算法。 –官网

直接拒绝

上面我们演示的例子效果都是直接拒绝,这里就不说了。

Warm Up

我们修改流控规则,阈值类型选择QPS,单机阈值为10,流控效果为Warm Up,预热时长为20,如下图所示:

通俗一点讲就是我们设置的阈值是10,预热时长是20。那么当大量请求同时涌入系统时,系统会经过20秒钟的预热才会一次处理10个请求,在20秒钟之内先期可能会处理3个、5个、8个再至10个
我们修改线程组线程数为15/s,一直发送。如下图所示:

http请求路径修改为最开始的/test/hello,如下图所示:

然后们启动JMeter发送请求,注意观察IDEA的控制台输出。

在刚开始的几秒中内每次只请求三次,如下图所示

运行到第6~8秒的时候QPS由4增加到5

在超出20秒以后QPS趋于稳定为10

匀速排队

匀速排队模式就相对简单了。JMeter我们不做改动,按照下图修改规则

这里的超时时间是毫秒,而Warm Up的预热时间单位是秒,这里要注意


控制台每秒打印输出的次数就是我们设置的阈值,这就是匀速排队的效果。

本系列专题源码已经上传至gitee:https://gitee.com/tide001/springcloud_parent,欢迎下载交流

以上是关于Sentinel.02.Sentinel之流量控制的主要内容,如果未能解决你的问题,请参考以下文章

服务端性能保障之流量并发控制方法

4-7:TCP协议之流量控制

防火墙基础之流量管理与控制

网络协议系列九 - 传输层-TCP之流量控制和拥塞控制

网络协议系列九 - 传输层-TCP之流量控制和拥塞控制

网络协议系列九 - 传输层-TCP之流量控制和拥塞控制