当前位置: 首页 > news >正文

Sentinel Client: 整合Apollo规则持久化

在前面的学习过程中,Sentinel 的规则,也就是我们之前定义的限流规则,是通过代码的方式定义好的。这是初始化时需要做的事情,Sentinel 提供了基于API的方式修改规则:

FlowRuleManager.loadRules(List<FlowRule> rules); // 修改流控规则
DegradeRuleManager.loadRules(List<DegradeRule> rules); // 修改降级规则
SystemRuleManager.loadRules(List<SystemRule> rules); // 修改系统规则
AuthorityRuleManager.loadRules(List<AuthorityRule> rules); // 修改授权规则

当我们接入了控制台后,可以通过控制台进行规则的动态修改,问题是当应用程序重启后规则信息就会恢复到初始化的阶段,也就是说后面修改的值会丢失,因为规则信息都是存储在应用的内存中。

为了解决这个问题Sentinel 提供了DataSource 扩展的功能,官方推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现 ReadableDataSource 接口端监听规则中心实时获取变更,流程如下:

1240

扩展的常见方式有推和拉两种模式:

  • 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;
  • 推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Apollo、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。

今天我们主要是讲如何使用 Apollo 来配置规则进行持久化,Apollo是携程开源的配置中心,非常好用

Github地址:https://github.com/ctripcorp/apollo

在我的书中也有对Apollo使用的详细介绍,等出版了再通知大家。

首先集成需要的依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-apollo</artifactId>
    <version>1.4.1</version>
</dependency>

然后创建 ApolloDataSource 并将其注册至对应的 RuleManager 上即可。比如:

private static void loadRules() {
        // Apollo 中的应用名称,自己定义的
        String appId = "SampleApp";
        // Apollo 的地址
        String apolloMetaServerAddress = "http://localhost:8080";
        System.setProperty("app.id", appId);
        System.setProperty("apollo.meta", apolloMetaServerAddress);
        // 指定环境
        System.setProperty("env", "DEV");
        // Apollo 的命名空间
        String namespaceName = "application";
        // 限流规则的Key, 在Apollo中用此Key
        String flowRuleKey = "flowRules";
        // 限流规则的默认值
        String defaultFlowRules = "[]";
        // 注册数据源
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
            flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
        }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}

到此为止配置就结束了,详细的解释我都写了注释哈。官方文档也是这么写的,问题是如果你刚接触会一头雾水的,为什么?

你不知道在Apollo中怎么配置啊,我们讲的就是说可以用Apollo来作为存储,持久化规则,那么规则怎么配置就需要我们自己去想。

我也是通过看源码才知道怎么去配置的,带着大家一起来看源码吧!

主要就是new ApolloDataSource这里,参数都是通过这里传进去的

public ApolloDataSource(String namespaceName, String flowRulesKey, String defaultFlowRuleValue,
                            Converter<String, T> parser) {
        super(parser);

        Preconditions.checkArgument(!Strings.isNullOrEmpty(namespaceName), "Namespace name could not be null or empty");
        Preconditions.checkArgument(!Strings.isNullOrEmpty(flowRulesKey), "FlowRuleKey could not be null or empty!");

        this.flowRulesKey = flowRulesKey;
        this.defaultFlowRuleValue = defaultFlowRuleValue;

        this.config = ConfigService.getConfig(namespaceName);

        initialize();

        RecordLog.info(String.format("Initialized rule for namespace: %s, flow rules key: %s",
            namespaceName, flowRulesKey));
    }

这边就是对传入的参数赋值,然后看下面这行:

this.config = ConfigService.getConfig(namespaceName);

这就是通过命名空间去Apollo中获取配置,获取完后就执行初始化

private void initialize() {
     initializeConfigChangeListener();
     loadAndUpdateRules();
}

initializeConfigChangeListener是初始化配置的监听器,当配置发生修改时会进入该监听器,也就是说在这个监听器里需要监听配置的修改,然后更新规则

 private void initializeConfigChangeListener() {
        config.addChangeListener(new ConfigChangeListener() {
            @Override
            public void onChange(ConfigChangeEvent changeEvent) {
                ConfigChange change = changeEvent.getChange(flowRulesKey);
                //change is never null because the listener will only notify for this key
                if (change != null) {
                    RecordLog.info("[ApolloDataSource] Received config changes: " + change.toString());
                }
                loadAndUpdateRules();
            }
        }, Sets.newHashSet(flowRulesKey));
 }

loadAndUpdateRules就是更新规则的逻辑了

private void loadAndUpdateRules() {
        try {
            T newValue = loadConfig();
            if (newValue == null) {
                RecordLog.warn("[ApolloDataSource] WARN: rule config is null, you may have to check your data source");
            }
            getProperty().updateValue(newValue);
        } catch (Throwable ex) {
            RecordLog.warn("[ApolloDataSource] Error when loading rule config", ex);
        }
 }

那么配置是怎么来的呢,请看loadConfig

 @Override
 public T loadConfig() throws Exception {
     return loadConfig(readSource());
 }

 public T loadConfig(S conf) throws Exception {
     T value = parser.convert(conf);
     return value;
 }

readSource就是获取我们配置的flowRulesKey的值,那么配置其实就是一个字符串,然后下面通过Json转换

 public String readSource() throws Exception {
     return config.getProperty(flowRulesKey, defaultFlowRuleValue);
 }

我们再返过来看看注册的代码:

 // 注册数据源
 ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
            flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
 }));

重点是ource -> JSON.parseObject(source, new TypeReference<List>()这行,这不就是转换成List吗,真相呼之欲出了,也就是在Apollo中配置的就是List的json格式就行。

我们配置一个试试看:

flowRules = [{"grade":1,"count":11,"resource":"HelloWorld"}]

点击保存并且发布,可以在initializeConfigChangeListener里面设置一个断点,你会发现,当发布配置之后,这边马上就会进来,然后执行其他的逻辑,到此为止整个流程结束。

欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course)

PS:目前星球中正在星主的带领下组队学习Sentinel,等你哦!

微信扫码加入猿天地知识星球

猿天地

转载于:https://www.cnblogs.com/yinjihuan/p/10634675.html

相关文章:

  • 2019.4.1 事务和隔离级别
  • [LOJ 6213]「美团 CodeM 决赛」radar
  • 一、ABP框架框架摘要
  • Java-Runoob-高级教程-实例-字符串:02. Java 实例 - 查找字符串最后一次出现的位置...
  • “尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。”...
  • Http input plugin
  • elasticsearch+logstash+kibana部署
  • 物联网的概念
  • 漂亮数组 Beautiful Array
  • es6常用功能与异步详解(JS高级面试题)
  • python----__str__与__repr__的区别
  • OpenCV入门学习资料汇总
  • 性能测试必知必会
  • Typora + Mathpix Snip,相见恨晚的神器
  • MongoDB 介绍
  • ----------
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • Cookie 在前端中的实践
  • JavaScript异步流程控制的前世今生
  • Java面向对象及其三大特征
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Meteor的表单提交:Form
  • Next.js之基础概念(二)
  • PHP的类修饰符与访问修饰符
  • Vue.js 移动端适配之 vw 解决方案
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • Yeoman_Bower_Grunt
  • 机器学习学习笔记一
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 微信支付JSAPI,实测!终极方案
  •  一套莫尔斯电报听写、翻译系统
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 再谈express与koa的对比
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • #define 用法
  • (Forward) Music Player: From UI Proposal to Code
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (LeetCode C++)盛最多水的容器
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (ros//EnvironmentVariables)ros环境变量
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转载)CentOS查看系统信息|CentOS查看命令
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .gitignore文件_Git:.gitignore
  • .gitignore文件---让git自动忽略指定文件
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .NET 发展历程
  • .NET 反射的使用
  • @property @synthesize @dynamic 及相关属性作用探究
  • [ MSF使用实例 ] 利用永恒之蓝(MS17-010)漏洞导致windows靶机蓝屏并获取靶机权限