zoukankan      html  css  js  c++  java
  • Sentinel的持久化

    官网地址:https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel

    一、规则管理及推送

    Sentinel-dashboard配置的规则是基于内存的,在微服务以及控制台重启的时候就清空了;

    一般来说,规则的推送有下面三种模式:

     1、原始模式

    如果不做任何修改,Dashboard 的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中;

    优缺点:这种做法的好处是简单,无依赖;坏处是应用重启规则就会消失,仅用于简单测试,不能用于生产环境

    2、Pull模式

      pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的 WritableDataSourceRegistry 中。

     

       首先 Sentinel 控制台通过 API 将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地的文件中。使用 pull 模式的数据源时一般不需要对 Sentinel 控制台进行改造。

      这种实现方法好处是简单,不引入新的依赖,坏处是无法保证监控数据的一致性。

    (1)通过SPI扩展机制进行扩展,在resources目录下创建 META-INF/services/com.alibaba.csp.sentinel.init.InitFunc 文件;我们写一个拉模式的实现类  com.yufeng.persistence.PullModeByFileDataSource ,并将这个类的全类名写入到文件中。

     (2)实现的类  PullModeByFileDataSource 类,如下:

      1 @Slf4j
      2 public class PullModeByFileDataSource implements InitFunc {
      3 
      4     @Override
      5     public void init() {
      6         log.info("time:{}读取配置", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")));
      7 
      8         // 1. 创建文件夹
      9         try {
     10             this.mkdirIfNotExits(PersistenceRuleConstant.storePath);
     11     
     12             // 2. 创建文件
     13             this.createFileIfNotExits(PersistenceRuleConstant.rulesMap);
     14     
     15             // 3.处理流控规则
     16             this.dealFlowRules();
     17     
     18             // 4.处理降级规则
     19             this.dealDegradeRules();
     20     
     21             // 5.处理系统规则
     22             this.dealSystemRules();
     23     
     24             // 6.处理热点参数规则
     25             this.dealParamFlowRules();
     26     
     27             // 7.处理授权规则
     28             this.dealAuthRules();
     29         } catch (IOException e) {
     30             log.error("错误原因:{}",e);
     31         }
     32     }
     33 
     34     /**
     35      * 处理流控规则
     36      */
     37     private void dealFlowRules() throws FileNotFoundException {
     38         String ruleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.FLOW_RULE_PATH).toString();
     39 
     40         // 1. 创建流控规则的可读数据源
     41         ReadableDataSource<String, List<FlowRule>> flowRuleRds = new FileRefreshableDataSource<> (
     42                 ruleFilePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
     43         );
     44 
     45         // 2. 将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
     46         FlowRuleManager.register2Property(flowRuleRds.getProperty());
     47 
     48         WritableDataSource<List<FlowRule>> flowRuleWds = new FileWritableDataSource<List<FlowRule>>(
     49                 ruleFilePath, JSON::toJSONString);
     50 
     51         // 3. 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
     52         // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
     53         WritableDataSourceRegistry.registerFlowDataSource(flowRuleWds);
     54     }
     55 
     56     /**
     57      * 降级规则
     58      */
     59     private void dealDegradeRules() throws FileNotFoundException {
     60         String degradeRuleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.DEGRAGE_RULE_PATH).toString();
     61 
     62         // 1. 创建流控规则的可读数据源
     63         ReadableDataSource<String, List<DegradeRule>> degradeRuleRds = new FileRefreshableDataSource<>(
     64                 degradeRuleFilePath, source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {})
     65         );
     66 
     67         // 2.将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
     68         DegradeRuleManager.register2Property(degradeRuleRds.getProperty());
     69 
     70         WritableDataSource<List<DegradeRule>> degradeRuleWds = new FileWritableDataSource<>(
     71                 degradeRuleFilePath, JSON::toJSONString
     72         );
     73 
     74         // 3. 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
     75         // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
     76         WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWds);
     77     }
     78 
     79     /**
     80      * 处理系统规则
     81      */
     82     private void dealSystemRules() throws FileNotFoundException {
     83         String systemRuleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.SYSTEM_RULE_PATH).toString();
     84 
     85         // 1.创建流控规则的可读数据源
     86         ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>(
     87                 systemRuleFilePath, source -> JSON.parseObject(source, new TypeReference<List<SystemRule>>() {})
     88         );
     89 
     90         // 2.将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
     91         SystemRuleManager.register2Property(systemRuleRDS.getProperty());
     92 
     93         WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(
     94                 systemRuleFilePath, JSON::toJSONString
     95         );
     96 
     97         // 3.将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
     98         // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
     99         WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
    100     }
    101 
    102     /**
    103      * 热点参数规则
    104      */
    105     private void dealParamFlowRules() throws FileNotFoundException {
    106         String paramFlowRuleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.HOT_PARAM_RULE).toString();
    107 
    108         // 1. 创建流控规则的可读数据源
    109         ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS = new FileRefreshableDataSource<>(
    110                 paramFlowRuleFilePath, source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {})
    111         );
    112 
    113         // 2. 将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
    114         ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());
    115 
    116         WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>(
    117                 paramFlowRuleFilePath, JSON::toJSONString
    118         );
    119 
    120         // 3. 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
    121         // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
    122         ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
    123     }
    124 
    125     /**
    126      * 方法实现说明:授权规则
    127      * @author:smlz
    128      * @return:
    129      * @exception:
    130      * @date:2019/11/29 13:56
    131      */
    132     private void dealAuthRules() throws FileNotFoundException {
    133         String authFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.AUTH_RULE_PATH).toString();
    134 
    135         // 1.创建流控规则的可读数据源
    136         ReadableDataSource<String, List<AuthorityRule>> authRuleRDS = new FileRefreshableDataSource<>(
    137                 authFilePath, source -> JSON.parseObject(source, new TypeReference<List<AuthorityRule>>() {})
    138         );
    139 
    140         // 2.将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
    141         AuthorityRuleManager.register2Property(authRuleRDS.getProperty());
    142 
    143         WritableDataSource<List<AuthorityRule>> authRuleWDS = new FileWritableDataSource<>(
    144                 authFilePath, JSON::toJSONString
    145         );
    146 
    147         // 3.将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
    148         // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
    149         WritableDataSourceRegistry.registerAuthorityDataSource(authRuleWDS);
    150     }
    151 
    152     /**
    153      * 创建文件目录
    154      */
    155     private void mkdirIfNotExits(String filePath) throws IOException {
    156         File file = new File(filePath);
    157         if(!file.exists()) {
    158             log.info("创建Sentinel规则目录:{}",filePath);
    159             file.mkdirs();
    160         }
    161     }
    162 
    163     /**
    164      * 创建规则文件
    165      */
    166     private void createFileIfNotExits(Map<String,String> ruleFileMap) throws IOException {
    167         for (Map.Entry entry : ruleFileMap.entrySet()) {
    168             String ruleFilePath  = PersistenceRuleConstant.rulesMap.get(entry.getKey()).toString();
    169             File ruleFile = new File(ruleFilePath);
    170             if(!ruleFile.exists()) {
    171                 log.info("创建Sentinel 规则文件:{}",ruleFile);
    172                 ruleFile.createNewFile();
    173             }
    174         }
    175     }
    176 }

    (3)常量类的定义

     1 public class PersistenceRuleConstant {
     2 
     3     /**
     4      * 存储文件路径
     5      */
     6     public static final String storePath = System.getProperty("user.home")+"\sentinel\rules\";
     7 
     8     /**
     9      * 各种存储sentinel规则映射map
    10      */
    11     public static final Map rulesMap = new HashMap<String,String>();
    12 
    13     //流控规则文件
    14     public static final String FLOW_RULE_PATH = "flowRulePath";
    15 
    16     //降级规则文件
    17     public static final String DEGRAGE_RULE_PATH = "degradeRulePath";
    18 
    19     //授权规则文件
    20     public static final String AUTH_RULE_PATH = "authRulePath";
    21 
    22     //系统规则文件
    23     public static final String SYSTEM_RULE_PATH = "systemRulePath";
    24 
    25     //热点参数文件
    26     public static final String HOT_PARAM_RULE = "hotParamRulePath";
    27 
    28     static {
    29         rulesMap.put(FLOW_RULE_PATH,storePath + "flowRule.json");
    30         rulesMap.put(DEGRAGE_RULE_PATH,storePath + "degradeRule.json");
    31         rulesMap.put(SYSTEM_RULE_PATH,storePath + "systemRule.json");
    32         rulesMap.put(AUTH_RULE_PATH,storePath + "authRule.json");
    33         rulesMap.put(HOT_PARAM_RULE,storePath + "hotParamRule.json");
    34     }
    35 }

     3、Push模式

      生产环境下一般更常用的是 push 模式的数据源。对于 push 模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不应由 Sentinel 客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel,而不是经 Sentinel 数据源推送至配置中心。这样的流程就非常清晰了:

     原理简述

    (1)控制台推送规则:

    •  将规则推送到Nacos或其他远程配置中心;
    • Sentinel客户端链接Nacos,获取规则配置;并监听Nacos配置变化,如发生变化,就更新本地缓存(从而让本地缓存总是和Nacos一致);

    (2)控制台监听Nacos配置变化,如发生变化就更新本地缓存(从而让控制台本地缓存总是和Nacos一致)

    改造方案

  • 相关阅读:
    android中提示&对话框----ProgressDialog&DatePickerDialog &TimePickerDialog&PopupWindow
    android中提示&对话框----AlertDialog
    android中提示&对话框----Notification
    android中提示&对话框----Toast
    android中与Adapter相关的控件----ViewFlipper
    android中与Adapter相关的控件----ExpandableListView
    android中与Adapter相关的控件----Spinner&AutoCompleteTextView
    android中与Adapter相关的控件----GridView
    android中与Adapter相关的控件----ListView
    android中Adapter适配器的讲解
  • 原文地址:https://www.cnblogs.com/yufeng218/p/15158945.html
Copyright © 2011-2022 走看看