1. 基本介绍

image.png

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

2. 流控模式

2.1 直接(默认)

直接 -> 快速失败(系统默认)

(1)配置及说明

QPS:表示1秒钟内查询1次就是OK,若超过次数1,就直接->快速失败,报默认错误
线程数:当调用该API的线程数达到阈值的时候,进行限流。
流控规则 - 图2

(2)测试

快速多次点击访问http://localhost:8401/testA

(3)结果

返回页面 Blocked by Sentinel (flow limiting)
image.png

(4)源码

com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController

(5)思考

直接调用默认报错信息,技术方面OK,但是,是否应该有我们自己的后续处理?类似有个fallback的兜底方法?

2.2 关联

(1)是什么

  • 当自己关联的资源达到阈值时,就限流自己
  • 当与A关联的资源B达到阀值后,就限流A自己(B惹事,A挂了)

(2)配置A

当关联资源/testB的QPS阀值超过1时,就限流/testA的Rest访问地址,当关联资源到阈值后限制配置好的资源名
image.png

(3)Postman模拟并发密集访问testB

流控规则 - 图5
Run - 大批量线程高并发访问http://localhost:8401/testB
Postman运行后,点击访问http://localhost:8401/testA,发现testA挂了

  • 结果Blocked by Sentinel(flow limiting)

    2.3 链路

只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【API级别的针对来源】

NodeSelectorSlot 中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一棵调用树。这棵树的根节点是一个名字为 machine-root 的虚拟节点,调用链的入口都是这个虚节点的子节点。
一棵典型的调用树如下图所示:

  1. machine-root
  2. / \
  3. / \
  4. Entrance1 Entrance2
  5. / \
  6. / \
  7. DefaultNode(nodeA) DefaultNode(nodeA)

上图中来自入口 Entrance1Entrance2 的请求都调用到了资源 NodeA,Sentinel 允许只根据某个入口的统计信息对资源限流。比如我们可以设置 strategyRuleConstant.STRATEGY_CHAIN,同时设置 refResourceEntrance1 来表示只有从入口 Entrance1 的调用才会记录到 NodeA 的限流统计当中,而不关心经 Entrance2 到来的调用。
调用链的入口(上下文)是通过 API 方法 ContextUtil.enter(contextName) 定义的,其中 contextName 即对应调用链路入口名称。详情可以参考 ContextUtil 文档

相关博客https://blog.csdn.net/qq_42362240/article/details/105861463

(1)业务类

package com.atguigu.speingcloud.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;

@Service
public class SentinelSerice {

    //@SentinelResource(value = "testA")
    public String testLianLu(){
        return "链路";
    }
}
package com.atguigu.speingcloud.controller;

import com.atguigu.speingcloud.service.SentinelSerice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class FlowLimitController {

    @Autowired
    private SentinelSerice serice;

    @GetMapping("/testA")
    public String testA()
    {
        return serice.testLianLu() + "------testA";
    }

    @GetMapping("/testB")
    public String testB()
    {
        log.info(Thread.currentThread().getName()+"\t"+"...testB");
        return serice.testLianLu() + "------testB";
    }
}

(2)新增流控规则

当前链路关系
image.png
新增规则
image.png
资源/testB的入口资源为sentinel_web_servlet_context

(3)测试

http://localhost:8401/testB请求超过阈值会报错
http://localhost:8401/testA则没影响

(4)结论

新增的流控规则入口资源配置为sentinel_web_servlet_context,意思为对从sentinel_web_servlet_context入口进来的调用到资源/testB的请求做限制,调用/testA则没影响

需要加@SentinelResource注解,资源才可生效,去除该注解后,流控规则失效(暂时不管,改代码了)

3. 流控效果

3.1 直接

直接->快速失败(默认的流控处理)
Blocked by Sentinel (flow limiting)

3.2 预热 Warm Up

Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过”冷启动”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。详细文档可以参考 流量控制 - Warm Up 文档,具体的例子可以参见 WarmUpFlowDemo。

通常冷启动的过程系统允许通过的 QPS 曲线如下图所示:
流控规则 - 图8

(1)公式

默认coldFactor为3,即请求QPS 从 threshold / 3开始,经预热时长逐渐升至设定的QPS阈值。

(2)源码

com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController

(3)WarmUp配置

**
案例,阀值为10+预热时长设置5秒。
系统初始化的阀值为10/ 3约等于3,即阀值刚开始为3;然后过了5秒后阀值才慢慢升高恢复到10
流控规则 - 图9

(4)测试

多次快速点击http://localhost:8401/testB - 刚开始(前五秒)不行,后续慢慢OK

(5)应用场景
**
如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。

3.3 排队等待

匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。详细文档可以参考 流量控制 - 匀速器模式,具体的例子可以参见 PaceFlowDemo

该方式的作用如下图所示:
流控规则 - 图10

这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

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

(1)设置:

/testA每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒。
流控规则 - 图11

(2)源码 -

com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController

(3)测试

添加日志记录代码到FlowLimitController的testA方法

@RestController
@Slf4j
public class FlowLimitController {
    @GetMapping("/testA")
    public String testA()
    {
        log.info(Thread.currentThread().getName()+"\t"+"...testA");//<----
        return "------testA";
    }

    ...
}
  • Postman模拟并发密集访问testA。

image.png

  • 后台结果

image.png