Spring Cloud Alibaba:Sentinel 流控规则

1. 前言

在前面的文章中,已经介绍过了 Sentinel安装和基本使用。这次主要讲的是Sentinel 的流量控制规则,使用版本为1.8.0,它提供了以下几个配置项:

在这里插入图片描述

  • 资源名: 唯一名称,默认是接口的请求路径
  • 针对来源: Sentinel可以针对调用者限流,填写微服务名称,默认default(不区分来源)
  • 阈值类型/单机阈值:
    • QPS:当调用该API的QPS达到阈值,进行限流
    • 线程数:当调用该API的线程数达到阈值,进行限流
  • 是否集群: 不需要
  • 流控模式:
    • 直接:该API达到限流条件,进行限流
    • 关联:当关联的资源达到阈值,就限流自己
    • 链路:只记录指定链路上的流量,指定资源从入口资源进来的流量,如果达到条件,就进行限流(API级别的针对来源)
  • 流控效果:
    • 快速失败:直接失败,抛出异常
    • Warm Up:根据codeFactor(冷加载因子,默认3),从 阈值/codeFactor 开始,经过配置的预热时长,才达到设定的QPS阈值
    • 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效

2. 阈值类型

2.1 QPS

Queries Per Second,每秒请求量。

首先,我们给 /test 接口配置如下流控规则。

配置项
QPS 10
流控规则 直接
流控效果 快速失败

接着,启动JMeter在1秒内发送20个请求。结果就是产生大量异常,直接报错Blocked by Sentinel (flow limiting) ,说明Sentinel拦截生效

在这里插入图片描述

2.2 线程数

将上一步的 QPS 改成 线程数,阈值设置为2,测试结果如下:
在这里插入图片描述
竟然所有请求都通过了,这是因为CPU的执行速度远远超出了我们的想象,并非每个HTTP请求都会New出新的线程进行执行,可能一个线程就全部处理掉了。为了让CPU创建大量线程,我们改下接口代码:

    @GetMapping("/test")
    public String test(){
    
    
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        return "test";
    }

重新执行JMeter,结果如下,符合预期:
在这里插入图片描述

3. 流控模式

3.1 直接

针对当前资源的接口进行控制,前面的例子用的就是这项配置

3.2 关联

当关联的资源达到阈值,就限流自己。例如:当支付接口的调用达到阈值,就限制下单接口。

创建另一个接口 /test2,针对/test资源配置如下限流规则:
在这里插入图片描述
接下来,使用JMeter对/test2接口发起大量请求。然后,立刻马上在浏览器访问/test,就能重现Blocked by Sentinel (flow limiting)的异常。这就是关联流控的使用方式。

3.3 链路

链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流;它的功能有点类似于针对 来源配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度更细.

举个例子:

创建一个OrderService,里面写个getOrder方法,并加上 @SentinelResource 注解,表示当前方法资源名称是 getOrder

@Service
public class OrderServiceImpl implements OrderService {
    
    

    @SentinelResource(value = "getOrder")
    @Override
    public String getOrder(String id) {
    
    
        return "Order:" + id;
    }
}

在controller分别创建2个接口:order1、order2

    @GetMapping("/order1")
    public String order1(){
    
    
        return orderService.getOrder("111");
    }

    @GetMapping("/order2")
    public String order2(){
    
    
        return orderService.getOrder("222");
    }

打开sentinel控制台,对getOrder资源进行流控规则设置。

入口资源设置为 /order1,表示从/order1接口调用才进行流控,如果从/order2调用的不做任何控制

在这里插入图片描述
在浏览器反复调用 http://localhost:8020/order1 ,发现流控没生效 - -!

这是因为从1.6.3 版本开始, Sentinel Web filter默认收敛所有URL的入口context

1.7.0 版本开始(对应Spring Cloud Alibaba的2.1.1.RELEASE),官方在引入了spring.cloud.sentinel.web-context-unify 参数,用于控制是否收敛context;将其配置为 false 即可根据不同的URL 进行链路限流。

官方源码如下:
在这里插入图片描述
如上图所示:web-context-unify 为true的时候,取到的是收敛的context名称sentinel_spring_web_context;为false的时候,就可以正确地取到 /order1 资源名。

在 application.yml 修改参数之后,再次测试,就能正常进行限流了

在这里插入图片描述

4. 流控效果

4.1 快速失败

抛出Blocked by Sentinel (flow limiting)异常,前面的例子用的就是这项配置

4.2 Warm Up

预热、冷启动

如下图,系统将从 10/冷却因子3 开始,经过10秒时间缓慢将阈值升到单机阈值10
在这里插入图片描述
配置JMeter,在30秒内发送300次请求,也就是10次/秒。 测试结果如下:

一开始的请求,存在大量报错,因为这时候阈值从3开始,还没达到10
在这里插入图片描述
到最后,阈值达到10了就不再报错

在这里插入图片描述

4.3 排队等待

严格地控制请求通过的间隔时间,也就是让请求匀速地通过,对应的是漏桶算法。这种方式适合用于请求以突刺状来到,这个时候我们不希望一下子把所有的请求都通过,这样可能会把系统压垮;同时我们也期待系统以稳定的速度,逐步处理这些请求,以起到“削峰填谷”的效果,而不是拒绝所有请求。

注意:匀速排队模式暂时不支持 QPS > 1000 的场景。

测试:设置QPS=1,也就是每秒处理1个请求,剩下的排队等待,5秒后超时
在这里插入图片描述
使用JMeter每秒发送2次请求
在这里插入图片描述

从第6秒开始,就开始出现超时异常
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_28834355/article/details/113192581