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 接口端监听规则中心实时获取变更,流程如下:
扩展的常见方式有推和拉两种模式:
- 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 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,等你哦!
Sentinel Client: 整合Apollo规则持久化的更多相关文章
- 阿里Sentinel控制台源码修改-对接Apollo规则持久化
改造背景 前面我们讲解了如何对接Apollo来持久化限流的规则,对接后可以直接通过Apollo的后台进行规则的修改,推送到各个客户端实时生效. 但还有一个问题就是Sentinel控制台没有对接Apol ...
- Spring Cloud Alibaba基础教程:Sentinel Dashboard同步Apollo存储规则
在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中.同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能 ...
- Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Apollo
在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中.同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能 ...
- [Spring-Cloud-Alibaba] Sentinel 规则持久化
在之前的练习中,只要应用重启,就需要重新配置,这样在我们实际的项目是非常不实用的,那么有没有办法把我们配置的规则保存下来呢?答案是YES,那么接下来,给大家来介绍如何将Sentinel规则持久化. D ...
- Sentinel基于Apollo的持久化改造
Sentinel基于Apollo的持久化改造 sentinel默认是将用户在dashboard中编辑过的流控信息保存在内存中,所以在重启后,所有之前配置过的流控规则也就不见了.但是sentinel给用 ...
- Sentinel Dashboard(基于1.8.1)流控规则持久化到Nacos——涉及部分Sentinel Dashboard源码改造
前言 之前虽然也一直在使用sentinel实现限流熔断功能,但却没有好好整理之前看的源码与资料,今天有时间将之前自己整理过的资料写成一篇博文,或者是是一篇关于Sentinel(基于目前最近版本1.8, ...
- Spring Cloud Alibaba学习笔记(7) - Sentinel规则持久化及生产环境使用
Sentinel 控制台 需要具备下面几个特性: 规则管理及推送,集中管理和推送规则.sentinel-core 提供 API 和扩展接口来接收信息.开发者需要根据自己的环境,选取一个可靠的推送规则方 ...
- sentinel 规则持久化到nacos
问题描述 Sentinel Dashboard中添加的规则是存储在内存中的,只要项目一重启规则就丢失了 此处将规则持久化到nacos中,在nacos中添加规则,然后同步到dashboard中: 后面研 ...
- Spring Cloud Alibaba基础教程:Sentinel使用Nacos存储规则
通过上一篇<使用Sentinel实现接口限流>的介绍,相信大家对Sentinel已经有了初步的认识.在Spring Cloud Alibaba的整合封装之下,接口限流这件事情可以非常轻易的 ...
随机推荐
- 后端必备的 Git 分支开发规范指南 转
原文链接 作者:稻草叔叔 http://juejin.im/post/5b4328bbf265da0fa21a6820 点击上方 "后端技术精选",选择 "置顶公众号&q ...
- Redis(七)分布式锁
前面学习了Redis的数据结构以及命令.Redis中的事务和Redis对Lua脚本的支持. 这一章就对Redis这些特性做一下实战性应用--基于Redis的分布式锁实现. Lock和Distribut ...
- 【Easyexcel】java导入导出超大数据量的xlsx文件 解决方法
解决方法: 使用easyexcel解决超大数据量的导入导出xlsx文件 easyexcel最大支持行数 1048576. 官网地址: https://alibaba-easyexcel.github. ...
- centos ftp服务器搭建 vsftpd 匿名访问配置方法 ftp 550 Failed to open file 错误处理
vsftpd是linux下常用的ftp服务软件,配置起来其实不复杂,只是网上很多文章,配置后都无法成功.我使用它是用于局域网内部分享文件的,所以使用匿名的方式. ftp本身密码是明文传输的,如果需要安 ...
- Yapi接口管理平台 本地部署 windows环境 -
YApi 是高效.易用.功能强大的 api 管理平台,旨在为开发.产品.测试人员提供更优雅的接口管理服务.可以帮助开发者轻松创建.发布.维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只 ...
- Mysql时区无法识别
Unable to connect to database. Tried 1 times {:error_message=>“Java::JavaSql::SQLException: The s ...
- Pinctrl子系统之一了解基础概念【转】
转自:https://blog.csdn.net/u012830148/article/details/80609337 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请 ...
- requests---HTTPS请求
做过接口测试的都会发现,现在的接口都是HTTPS协议了,今天就写一篇如何通过request发送https请求,如果不是很了解HTTP协议的同学可以看下我的另外一篇博客什么是HTTP 什么是HTTPS ...
- NLP中的预训练语言模型(四)—— 小型化bert(DistillBert, ALBERT, TINYBERT)
bert之类的预训练模型在NLP各项任务上取得的效果是显著的,但是因为bert的模型参数多,推断速度慢等原因,导致bert在工业界上的应用很难普及,针对预训练模型做模型压缩是促进其在工业界应用的关键, ...
- Pytorch中Module,Parameter和Buffer的区别
下文都将torch.nn简写成nn Module: 就是我们常用的torch.nn.Module类,你定义的所有网络结构都必须继承这个类. Buffer: buffer和parameter相对,就是指 ...