• 3、Sentinel 动态限流规则


    Sentinel 的理念是开发者只需要关注资源的定义,当资源定义成功后可以动态增加各种流控降级规则。Sentinel 提供两种方式修改规则:

    • 通过 API 直接修改 (loadRules)

    • 通过 DataSource 适配不同数据源修改

    通过 API 修改比较直观,可以通过以下几个 API 修改不同的规则:

    FlowRuleManager.loadRules(List rules); // 修改流控规则
    DegradeRuleManager.loadRules(List rules); // 修改降级规则
    手动修改规则(硬编码方式)一般仅用于测试和演示,生产上一般通过动态规则源的方式来动态管理规则。

    3.1 DataSource
    上述 loadRules() 方法只接受内存态的规则对象,但更多时候规则存储在文件、数据库或者配置中心当中。DataSource 接口给我们提供了对接任意配置源的能力。相比直接通过 API 修改规则,实现 DataSource 接口是更加可靠的做法。

    我们推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现 ReadableDataSource 接口端监听规则中心实时获取变更,流程如下:
    在这里插入图片描述
    DataSource 扩展常见的实现方式有:

    • 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;

    • 推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。

    Sentinel 目前支持以下数据源扩展:

    • Pull-based: 动态文件数据源、Consul, Eureka

    • Push-based: ZooKeeper, Redis, Nacos, Apollo, etcd

    2.3.2 poll
    实现拉模式的数据源最简单的方式是继承AutoRefreshDataSource抽象类,然后实现 readSource() 方法,在该方法里从指定数据源读取字符串格式的配置数据。比如基于文件的数据源

    2.3.3 push
    实现推模式的数据源最简单的方式是继承AbstractDataSource抽象类,在其构造方法中添加监听器,并实现 readSource() 从指定数据源读取字符串格式的配置数据。基于 Nacos 的数据源

    2.3.4 注册数据源
    通常需要调用以下方法将数据源注册至指定的规则管理器中:

    ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, parser);
    FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    
    • 1
    • 2

    若不希望手动注册数据源,可以借助 Sentinel 的 InitFunc SPI 扩展接口。只需要实现自己的 InitFunc 接口,在 init 方法中编写注册数据源的逻辑。比如:

    package com.test.init;
    
    public class DataSourceInitFunc implements InitFunc {
    
        @Override
        public void init() throws Exception {
            final String remoteAddress = "localhost";
            final String groupId = "Sentinel:Demo";
            final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule";
    
            ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId,
                source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
            FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    接着将对应的类名添加到位于资源目录(通常是 resource 目录)下的 META-INF/services 目录下的 com.alibaba.csp.sentinel.init.InitFunc 文件中,比如:

    com.test.init.DataSourceInitFunc
    这样,当初次访问任意资源的时候,Sentinel 就可以自动去注册对应的数据源了。

    2.3.5 示例
    代码见springboot-sentinel1项目

    2.3.5.1 InitFunc
    可以通过Sentinel的InitFunc SPI来实现接口的扩展,从而配置限流规则

    public class FlowRuleInitFunc implements InitFunc{
      @Override
      public void init() throws Exception {
        List<FlowRule> rules=new ArrayList<>();
        FlowRule rule=new FlowRule();
        rule.setResource("doTest");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(5);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
     }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    • 在META-INF/services/com.alibaba.csp.sentinel.init.InitFunc文件中,添加自定义扩展点的全路径

    • 重启服务之后,会触发限流。

    2.3.2.2 扩展Nacos数据源
    • 添加Nacos Datasouce依赖

    <dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-datasource-nacos</artifactId>
      <version>1.8.0</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    • 修改数据源加载方式

    public class DataSourceInitFunc implements InitFunc{
      private final String remoteAddress="192.168.216.128"; //Nacos 远程服务host
      private final String groupId="SENTINEL_GROUP"; //Nacos GroupID
      private final String dataId="com.gupaoedu.sentinel.demo.flow.rule";
      @Override
      public void init() throws Exception {
        ReadableDataSource<String,List<FlowRule>> flowRuleDataSource=
            new NacosDataSource<>(remoteAddress,groupId,dataId,
                source-> JSON.parseObject(source,new
    TypeReference<List<FlowRule>>(){}));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
     }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    • 在Nacos上添加配置
    在这里插入图片描述
    • 通过访问测试,即可看到被限流的效果。

    • 也可以在 ${用户}/logs/csp/sentinel-record.log.2020-09-22 文件中看到sentinel启动过程中动态数据源的加载过程。

    2.3.6 基于配置文件
    基于配置文件的动态限流

    spring.cloud.sentinel.transport.clientIp=192.168.216.128:7777
    spring.cloud.sentinel.datasource.nacos.nacos.serverAddr=192.168.216.128:8848
    spring.cloud.sentinel.datasource.nacos.nacos.dataId=com.gupaoedu.sentinel.demo.flow.rule
    spring.cloud.sentinel.datasource.nacos.nacos.groupId=SENTINEL_GROUP
    spring.cloud.sentinel.datasource.nacos.nacos.dataType=json
    spring.cloud.sentinel.datasource.nacos.nacos.ruleType=flow
    spring.cloud.sentinel.datasource.nacos.nacos.username=nacos
    spring.cloud.sentinel.datasource.nacos.nacos.password=nacos
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    【opencv】Opencv中数据类型CV_8U, CV_16U, CV_16S, CV_32F、CV_64F
    Unity下如何实现RTMP或RTSP播放端录像?
    Kubernetes 进阶训练营 控制器
    deepstream python yolov5使用记录
    【知识点随笔分析 | 第六篇】HTTP/1.1,HTTP/2和HTTP/3的区别
    在Windows电脑上用多开器玩网络游戏的技巧
    C/C++ 实现动态资源文件释放
    vue js中使用typeof和Object.prototype.toString.call()判断类型(超详细),浅析call()和apply()的区别
    2022年全国大学生数学建模竞赛E题思路
    面试突击82:SpringBoot 中如何操作事务?
  • 原文地址:https://blog.csdn.net/weixin_45817985/article/details/134228400