您的位置:首页 > 编程语言 > Java开发

[Spring-Cloud-Alibaba] Sentinel 规则持久化

2019-07-22 20:02 1366 查看

在之前的练习中,只要应用重启,就需要重新配置,这样在我们实际的项目是非常不实用的,那么有没有办法把我们配置的规则保存下来呢?答案是YES,那么接下来,给大家来介绍如何将Sentinel规则持久化。

Document: 传送门

  • File Datasource(文件存储) Pull 模式
  • Push 模式
  • Nacos configuration
  • Apollo
  • File Datasource
    Pull 模式

    原理:
    扩展写数据源(

    WritableDataSource
    ), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等
    pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的
    WritableDataSourceRegistry
    中。

    过程如下:

    Pull Demo
    • Step 1: 添加配置

      <dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-datasource-extension</artifactId>
      </dependency>
    • Step 2: 编写持久化代码,实现

      com.alibaba.csp.sentinel.init.InitFunc

      代码参考自:传送门
    import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;
    import com.alibaba.csp.sentinel.datasource.*;
    import com.alibaba.csp.sentinel.init.InitFunc;
    import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
    import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
    import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
    import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
    import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
    import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
    import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
    import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
    import com.alibaba.csp.sentinel.slots.system.SystemRule;
    import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
    import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.TypeReference;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    
    /**
    * FileDataSourceInit for : 自定义Sentinel存储文件数据源加载类
    *
    * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
    * @since 2019/7/21
    */
    public class FileDataSourceInit implements InitFunc {
    @Override
    public void init() throws Exception {
    // TIPS: 如果你对这个路径不喜欢,可修改为你喜欢的路径
    String ruleDir = System.getProperty("user.home") + "/sentinel/rules";
    String flowRulePath = ruleDir + "/flow-rule.json";
    String degradeRulePath = ruleDir + "/degrade-rule.json";
    String systemRulePath = ruleDir + "/system-rule.json";
    String authorityRulePath = ruleDir + "/authority-rule.json";
    String hotParamFlowRulePath = ruleDir + "/param-flow-rule.json";
    
    this.mkdirIfNotExits(ruleDir);
    this.createFileIfNotExits(flowRulePath);
    this.createFileIfNotExits(degradeRulePath);
    this.createFileIfNotExits(systemRulePath);
    this.createFileIfNotExits(authorityRulePath);
    this.createFileIfNotExits(hotParamFlowRulePath);
    // 流控规则
    ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(
    flowRulePath,
    flowRuleListParser
    );
    // 将可读数据源注册至FlowRuleManager
    // 这样当规则文件发生变化时,就会更新规则到内存
    FlowRuleManager.register2Property(flowRuleRDS.getProperty());
    WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(
    flowRulePath,
    this::encodeJson
    );
    // 将可写数据源注册至transport模块的WritableDataSourceRegistry中
    // 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
    WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
    
    // 降级规则
    ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>(
    degradeRulePath,
    degradeRuleListParser
    );
    DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());
    WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>(
    degradeRulePath,
    this::encodeJson
    );
    WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);
    
    // 系统规则
    ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>(
    systemRulePath,
    systemRuleListParser
    );
    SystemRuleManager.register2Property(systemRuleRDS.getProperty());
    WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(
    systemRulePath,
    this::encodeJson
    );
    WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
    
    // 授权规则
    ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new FileRefreshableDataSource<>(
    flowRulePath,
    authorityRuleListParser
    );
    AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());
    WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>(
    authorityRulePath,
    this::encodeJson
    );
    WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);
    
    // 热点参数规则
    ReadableDataSource<String, List<ParamFlowRule>> hotParamFlowRuleRDS = new FileRefreshableDataSource<>(
    hotParamFlowRulePath,
    hotParamFlowRuleListParser
    );
    ParamFlowRuleManager.register2Property(hotParamFlowRuleRDS.getProperty());
    WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>(
    hotParamFlowRulePath,
    this::encodeJson
    );
    ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
    }
    
    /**
    * 流控规则对象转换
    */
    private Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject(
    source,
    new TypeReference<List<FlowRule>>() {
    }
    );
    /**
    * 降级规则对象转换
    */
    private Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(
    source,
    new TypeReference<List<DegradeRule>>() {
    }
    );
    /**
    * 系统规则对象转换
    */
    private Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(
    source,
    new TypeReference<List<SystemRule>>() {
    }
    );
    
    /**
    * 授权规则对象转换
    */
    private Converter<String, List<AuthorityRule>> authorityRuleListParser = source -> JSON.parseObject(
    source,
    new TypeReference<List<AuthorityRule>>() {
    }
    );
    
    /**
    * 热点规则对象转换
    */
    private Converter<String, List<ParamFlowRule>> hotParamFlowRuleListParser = source -> JSON.parseObject(
    source,
    new TypeReference<List<ParamFlowRule>>() {
    }
    );
    
    /**
    * 创建目录
    *
    * @param filePath
    */
    private void mkdirIfNotExits(String filePath) {
    File file = new File(filePath);
    if (!file.exists()) {
    file.mkdirs();
    }
    }
    
    /**
    * 创建文件
    *
    * @param filePath
    * @throws IOException
    */
    private void createFileIfNotExits(String filePath) throws IOException {
    File file = new File(filePath);
    if (!file.exists()) {
    file.createNewFile();
    }
    }
    
    private <T> String encodeJson(T t) {
    return JSON.toJSONString(t);
    }
    }
  • Step 3: 启用上述代码

    resource 目录下创建

    resources/META-INF/services
    目录并创建文件
    com.alibaba.csp.sentinel.init.InitFunc
    ,内容为:

    com.sxzhongf.sharedcenter.configuration.sentinel.datasource.FileDataSourceInit
  • Pull 优缺点
    • 优点
        简单,无任何依赖
      1. 没有额外依赖
    • 缺点
        不保证一致性(规则是使用
        FileRefreshableDataSource
        定时更新,会有延迟)
      1. 实时性不保证(规则是使用
        FileRefreshableDataSource
        定时更新)
      2. 拉取过于频繁也可能会有性能问题
      3. 由于文件存储于本地,容易丢失
    • 参考资料:
        ITMUCH
      1. Sentinel WIKI
    Push 模式

    推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现

    ReadableDataSource
    接口端监听规则中心实时获取变更,流程如下:

    <img src="https://user-images.githubusercontent.com/9434884/45406233-645e8380-b698-11e8-8199-0c917403238f.png" width="500" />

    • 实现原理

        控制台推送规则到Nacos/远程配置中心
      1. Sentinel client 舰艇Nacos配置变化,更新本地缓存
    • shared_center service 加工

        添加依赖
      <dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-datasource-nacos</artifactId>
      </dependency>
      1. 添加配置
      spring:
      cloud:
      sentinel:
      datasource:
      sxzhongf_flow:
      nacos:
      server-addr: localhost:8848
      dataId: ${spring.application.name}-flow-rules
      groupId: SENTINEL_GROUP
      # 规则类型,取值见:org.springframework.cloud.alibaba.sentinel.datasource.RuleType
      rule_type: flow
      sxzhongf_degrade:
      nacos:
      server-addr: localhost:8848
      dataId: ${spring.application.name}-degrade-rules
      groupId: SENTINEL_GROUP
      rule-type: degrade
    • Sentinel dashboard 加工

      Dashboard 规则改造主要通过2个接口:

      com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider
      &
      com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher

      Download Sentinel Source Code

    • 修改原
      sentinel-dashboard
      项目下的POM文件
    <!-- for Nacos rule publisher sample -->
    <dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <!--注释掉原文件中的scope,让其不仅在test的时候生效-->
    <!--<scope>test</scope>-->
    </dependency>
    • 偷懒模式:复制
      sentinel-dashboard
      项目下test下的nacos包(

    src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos
    src/main/java/com/alibaba/csp/sentinel/dashboard/rule

    • 修改controller中的默认provider & publisher

    com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2

    @Autowired
    // @Qualifier("flowRuleDefaultProvider")
    @Qualifier("flowRuleNacosProvider")
    private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
    @Autowired
    // @Qualifier("flowRuleDefaultPublisher")
    @Qualifier("flowRuleNacosPublisher")
    private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
    • 打开
      /Sentinel-1.6.2/sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html
      文件,修改代码:
    <!--<li ui-sref-active="active">-->
    <!--<a ui-sref="dashboard.flow({app: entry.app})">-->
    <!--<i class="glyphicon glyphicon-filter"></i>  流控规则 V1</a>-->
    <!--</li>-->
    
    ---
    
    改为
    
    <li ui-sref-active="active">
    <a ui-sref="dashboard.flow({app: entry.app})">
    <i class="glyphicon glyphicon-filter"></i>  NACOS 流控规则 V1</a>
    </li>

    Dashboard中要修改的代码已经好了。

  • 重新启动 Sentinel-dashboard

    mvn clean package -DskipTests

  • 测试效果

    Sentinel 添加流控规则:

    Nacos 查看同步的配置:

  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: