springcloud(9.3)Alibaba-Sentinel 限流管理

本文档介绍了如何在SpringCloud中使用Alibaba Sentinel进行限流操作,包括基于并发线程数和QPS的限流策略。详细讲解了Sentinel的限流概念、配置步骤、限流方式(抛异常、返回Boolean值、注解方式),并提供了注解方式的详细用法,包括版本差异和异常处理。通过实现CommandLineRunner接口或@PostConstruct注解加载限流规则,以及如何处理FlowException异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sentinel 的限流操作是在 前几篇相关博文的代码基础上 修改的!!!!!

https://blog.youkuaiyun.com/lettuce_/article/details/102568573

限流:

当我们设计了一个函数,准备上线,这时候这个函数会消耗一些资源,处理上限是1秒服务3000个QPS,但如果实际情况遇到高于3000的QPS该如何解决呢?Sentinel提供了两种流量统计方式,一种是统计并发线程数,另外一种则是统计 QPS,当并发线程数超出某个设定的阀值,新的请求会被立即拒绝,当QPS超出某个设定的阀值,系统可以通过直接拒绝、冷启动、匀速器三种方式来应对,从而起流量控制的作用。

基本概念:

资源Resource:可以是任意对象,一个字符串、一个方法,一个类对象;

规则Rule:需要如何限制或者降级,比如按照“QPS/失败比率”做出相应的处理;

入口Entry:每次资源调用都会创建一个Entry对象,Entry 创建的时候,同时也会创建一系列功能插槽
(slot chain),链里面的slot各司其职,比如其中的FlowSlot 则用于根据预设的限流规则
以及前面 slot 统计的状态,来进行流量控制,DegradeSlot 则通过统计信息以及预设的规则,来
做熔断降级;AuthoritySlot 则根据配置的黑白名单和调用来源信息,来做黑白名单控制;

操作:

1. 添加 jar包依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>0.2.1.RELEASE</version>
        </dependency>

有些博客说 引入许多依赖: 

但这些 使用 spring-cloud-starter-alibaba-sentinel 一个就可以引入全部

2. 修改配置文件

和上一篇博文的配置文件一样,具体可查询上一篇博文

3. 限流方式

3.1 使用 抛异常方式:

try (Entry entry=SphU.entry("resourceName")){
    //被保护的业务逻辑代码块(资源)
    //do something here 
}catch(BlockException e){
    //阻止资源访问
    //相关限流降级操作
}finally{
    if (entry!=null){
        entry.exit();
    }
}

3.2 使用 返回Boolean 值方式:

当程序发生限流后,会返回false值,这时可根据返回值进行限流后的逻辑操作处理

if (SphO.entry("被保护的业务(资源)名")){
    try{

    //被保护的业务逻辑(资源)
    }finally{
        SphO.exit();
    }

}else {
    //阻止资源访问
    //相关限流降级操作

}

3.3 使用 注解方式:(推荐)

主要使用 @SentinelResource 注解,该注解定义在需要限流操作的接口的方法上。

属性作用是否必须
value资源名称
entryTypeentry类型,标记流量的方向,取值IN/OUT,默认是OUT
blockHandler处理BlockException的函数名称。函数要求:
1. 必须是 public
2.返回类型与原方法一致
3. 参数类型需要和原方法相匹配,并在最后加 BlockException 类型的参数
4. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法。
blockHandlerClass存放blockHandler的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同blockHandler。 否 fallback 用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求:
1. 返回类型与原方法一致
2. 参数类型需要和原方法相匹配,Sentinel 1.6开始,也可在方法最后加 Throwable 类型的参数。
3.默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定fallbackClass里面的方法。
fallback用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求:
1. 返回类型与原方法一致
2. 参数类型需要和原方法相匹配,Sentinel 1.6开始,也可在方法最后加 Throwable 类型的参数。
3.默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定fallbackClass里面的方法。
fallbackClass【1.6】存放fallback的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同fallback。
defaultFallback【1.6】用于通用的 fallback 逻辑。默认fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,以fallback为准。函数要求:
1. 返回类型与原方法一致
2. 方法参数列表为空,或者有一个 Throwable 类型的参数。
3. 默认需要和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定 fallbackClass 里面的方法。
exceptionsToIgnore【1.6】指定排除掉哪些异常。排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。
exceptionsToTrace需要trace的异常Throwable

TIPS

  • 1.6.0 之前的版本 fallback 函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理
  • 若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandlerfallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出
  • 从 1.4.0 版本开始,注解方式定义资源支持自动统计业务异常,无需手动调用 Tracer.trace(ex) 来记录业务异常。Sentinel 1.4.0 以前的版本需要自行调用 Tracer.trace(ex) 来记录业务异常。

1. 在controller的限流方法上添加注解

@Controller
public class ProductController {
 
	@Autowired
    ProductService productService;

    /**
     * 被限流 的方法
     * @param m
     * @return
     */
    //value 随便命名,后规则中会调用该名
	@SentinelResource(value = "getProducts")
    @RequestMapping("/getProducts")
    public Object products(Model m) {
    	List<Product> ps = productService.listProducts();
    	m.addAttribute("ps", ps);
        return "products";
    }
}

2. 定义限流的规则类

@Component
public class RuleConfig implements CommandLineRunner {
    public void initFlowRule(){
        FlowRule flowRule=new FlowRule();
        flowRule.setResource("getProducts");//@SentinelResource 中定义的value
        flowRule.setCount(1); //限流阈值
        flowRule.setGrade(1); // 限流阈值类型(QPS 或并发线程数),默认为1 QPS

        //将该规则加载进 系统中
        List<FlowRule> list=new ArrayList<>();
        list.add(flowRule);
        FlowRuleManager.loadRules(list);
    }

    @Override
    public void run(String... args) throws Exception {
        this.initFlowRule();
    }
}

 

一条限流规则主要由下面几个因素组成:

resource:资源名,即限流规则的作用对象
count: 限流阈值
grade: 限流阈值类型(QPS 或并发线程数) 
limitApp: 流控针对的调用来源,若为 default 则不区分调用来源
strategy: 调用关系限流策略
controlBehavior: 流量控制效果(直接拒绝、Warm Up、匀速排队)

为实现在项目 启动后,规则类加载进系统中运行,有两种方式:

A.  需让规则类实现springboot的 CommandLineRunner 接口,并在该类上添加@Component 注解

CommandLineRunner  详情查看:https://www.cnblogs.com/myblogs-miller/p/9046425.html

B. 使用  @Configuration 配合 @PostConstruct 注解使用(两种方式效果一样)

@Configuration
public class RuleConfig{

    @PostConstruct
    public void initFlowRule(){
        FlowRule flowRule=new FlowRule();
        flowRule.setResource("getProducts");//@SentinelResource 中定义的value
        flowRule.setCount(1); //限流阈值
        flowRule.setGrade(1); // 限流阈值类型(QPS 或并发线程数),默认为1 QPS

        //将该规则加载进 系统中
        List<FlowRule> list=new ArrayList<>();
        list.add(flowRule);
        FlowRuleManager.loadRules(list);
        System.out.println("*************限流规则 initFlowRule() 已加载");
    }

}

3. 启动项目,快速多次访问 接口出现异常,限流成功

关于出现FlowException  的解释:  (FlowException  的父类为BlockException

controlBehavior
流控策略,主要是发生拦截后具体的流量整形和控制策略,目前有三种策略,分别是:

CONTROL_BEHAVIOR_DEFAULT
这种方式是:直接拒绝,该方式是默认的流量控制方式,当 qps 超过任意规则的阈值后,新的请求就
会被立即拒绝,拒绝方式为抛出FlowException。

这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位。

CONTROL_BEHAVIOR_WARM_UP
这种方式是:排队等待 ,又称为 冷启动。该方式主要用于当系统长期处于低水位的情况下,
流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。

通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个
预热的时间,避免冷系统被压垮的情况。

CONTROL_BEHAVIOR_RATE_LIMITER
这种方式是:慢启动,又称为 匀速器模式。这种方式严格控制了请求通过的间隔时间,也即是让
请求以均匀的速度通过,对应的是漏桶算法。

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

 4. 处理 FlowException  异常

创建一个 用来处理异常的类,类中定义出现异常后处理的方法,与@SentinelResource 相对应

public class BlockExceptionUtil {
    public static  Object returnBlockExceptionInfo(Model m, BlockException e){
        Product product=new Product();
        product.setId(0);
        product.setName("你的访问太频繁,请稍后");
        List<Product> ps = new ArrayList<>();
        ps.add(product);
        m.addAttribute("ps", ps);
        System.out.println("BlockException 被执行");
        return "products";
    }
}

修改 @SentinelResource 注解

@SentinelResource(value = "getProducts",blockHandlerClass = BlockExceptionUtil.class,blockHandler = "returnBlockExceptionInfo")
    

注意:

  • 如果不写blockHandlerClass ,则 blockHandler 引用的方法默认需要和原方法在同一个类中(@SentinelResource所在的类中)
  • blockHandler 对应的方法必需为 static ,否则无法解析
  • blockHandler 对应的方法 的传参中得加入  BlockException参数

快速多次访问 接口,则出现

 

相关的限流规则的种类及继承(实现)关系:

---Rule 【interface】
------AbstractRule【abstract class】
---------FlowRule【class】FlowRuleManager流量控制规则
---------AuthorityRule【class】AuthorityRuleManager              来源访问控制规则
---------SysteRule【class】SysteRuleManager     系统负载规则
---------DegradeRule【class】DegradeRuleManager             熔断降级规则
---------ParamfRule【class】ParamfRuleManager热点参数规则

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值