基于Nacos实现Sentinel规则持久化

基于Nacos实现Sentinel规则持久化

  • 一、Sentinel使用痛点
  • 二、解决方案
    • 2.1 保存本地文件
    • 2.2 保存数据库
    • 2.3 保存到Nacos
  • 三、规则持久化到Nacos
    • 3.1 Nacos服务端修改配置
    • 3.2 Sentinel控制台修改配置
    • 3.3 Nacos数据源整合到Sentinel中

一、Sentinel使用痛点

SpringCloudAlibaba帮我们提供了微服务的限流、熔断、降级组件Sentinel。并且它的功能非常强大,使用起来也非常方便,只需要给需要限流的资源添加注解,配置对应的规则,就能实现效果。(使用可以参考Sentinel使用)但是有个问题就是Sentinel的规则是保存在客户端的内存中,控制台(服务端)查询规则也是基于客户端内存查询。

这样就存在一个很严重的问题,如果客户端发生了重启那么配置的众多规则都会失效。想想都觉得很严重,谁还敢在生产环境使用它。那么基于这个问题,我们有多种方案可以来解决。

二、解决方案

2.1 保存本地文件

既然是担心规则保存在客户端内存中会丢失,那么我们可以将规则持久化到本地文件,但是这样也有一个问题,如果微服务是高可用部署,有多个实例节点,那么保存到本地文件就不可取了。

2.2 保存数据库

将规则持久化到数据库中,这样多个节点访问同一个数据库也能拿到配置,这样的缺点是如果规则变化从数据库中直接修改,微服务则没那么容易感知到变化,不过也不是解决不了,可以使用canel组件,监听mysql的binlog日志,从而刷新规则,但这这样又要引入新的中间件,增加了系统的复杂性。

2.3 保存到Nacos

我们知道nacos的客户端在启动时会主动从服务端拉取一次配置,之后会通过延迟定时任务拉取配置,同时对配置文件配置监听器。双层保证服务端的变化能被客户端感知到,基于Nocos本来的特性,再整合Sentinel的扩展点,我们就可以实现如下图的结构。
在Nacos服务端或者Sentinel控制台修改配置,都能将规则推送到Sentinel客户端。并且在Nacos服务端修改配置规则Sentinel控制台的规则会发生变化,在Sentinel控制台修改规则,Naocs的配置文件就会发生变化。
在这里插入图片描述

三、规则持久化到Nacos

梳理一下配置变更的两条线

  1. Nacos服务端修改配置,规则同步到Sentinel客户端及Sentinel控制台
  2. Sentinel控制台修改配置,规则同步到Sentinel客户端和Nacos服务端

3.1 Nacos服务端修改配置

  1. 我们在使用nacos作为规则持久化时需要引入一下相关依赖。
 <!--sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!--sentinel持久化 --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency><!-- nacos服务注册与发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
  1. spring-cloud-starter-alibaba-sentinel这个依赖会包含spring-cloud-starter-alibaba-sentinel-datasource
    在这里插入图片描述
  2. spring-cloud-starter-alibaba-sentinel-datasource依赖中引入了关键类NacosDataSourceFactoryBean
    在这里插入图片描述
  3. NacosDataSourceFactoryBean的构造方法中实例化了NacosDataSource
public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource> {
public NacosDataSource getObject() throws Exception {// 中间代码省略...return new NacosDataSource(properties, this.groupId, this.dataId, this.converter);}
}
  1. NacosDataSource由sentinel-datasource-nacos依赖引入
    在这里插入图片描述
  2. NacosDataSource的构造方法中会定义监听器,并且将监听器和配置文件绑定,这样当Nacos服务端修改配置后,客户端就能拿到最新的规则,并且将规则更新内存中。同时会先从Nacos服务拉去一次配置做初始化。
public NacosDataSource(final Properties properties, final String groupId, final String dataId, Converter<String, T> parser) {super(parser);this.pool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(1), new NamedThreadFactory("sentinel-nacos-ds-update", true), new DiscardOldestPolicy());this.configService = null;if (!StringUtil.isBlank(groupId) && !StringUtil.isBlank(dataId)) {AssertUtil.notNull(properties, "Nacos properties must not be null, you could put some keys from PropertyKeyConst");this.groupId = groupId;this.dataId = dataId;this.properties = properties;// 1.定义监听器,当配置发生变更监听器就能获取最新的配置this.configListener = new Listener() {public Executor getExecutor() {return NacosDataSource.this.pool;}public void receiveConfigInfo(String configInfo) {RecordLog.info("[NacosDataSource] New property value received for (properties: {}) (dataId: {}, groupId: {}): {}", new Object[]{properties, dataId, groupId, configInfo});T newValue = NacosDataSource.this.parser.convert(configInfo);NacosDataSource.this.getProperty().updateValue(newValue);}};// 2.将监听器和配置文件绑定this.initNacosListener();// 3.从Nacos服务端拉取配置放在内存中this.loadInitialConfig();} else {throw new IllegalArgumentException(String.format("Bad argument: groupId=[%s], dataId=[%s]", groupId, dataId));}}

3.2 Sentinel控制台修改配置

  1. Sentinel控制台发布规则后会调用Sentinel客户端的ModifyRulesCommandHandler,将修改的规则传过来。

  2. ModifyRulesCommandHandler的handle方法中是真正的处理逻辑,这里以流控规则为例,其他规则一样只是代码没展示。在Handle方法中会先将最新的规则加载到内存中,并且进行规则的持久化处理。

@CommandMapping(name = "setRules", desc = "modify the rules, accept param: type={ruleType}&data={ruleJson}")
public class ModifyRulesCommandHandler implements CommandHandler<String> {
@Overridepublic CommandResponse<String> handle(CommandRequest request) {// 省略部分代码...if (FLOW_RULE_TYPE.equalsIgnoreCase(type)) {List<FlowRule> flowRules = JSONArray.parseArray(data, FlowRule.class);// 1.将规则加载到内存中FlowRuleManager.loadRules(flowRules);// 2.规则持久化(如果增加了扩展,默认没有实现)if (!writeToDataSource(getFlowDataSource(), flowRules)) {result = WRITE_DS_FAILURE_MSG;}return CommandResponse.ofSuccess(result);}
}
  1. 上面的持久化最终会调用到我们自己实现的Nacos实现类中,最终将配置发布到Nacos服务端。
public class NacosWritableDataSource<T> implements WritableDataSource<T> {
@Overridepublic void write(T t) throws Exception {lock.lock();try {configService.publishConfig(dataId, groupId, this.configEncoder.convert(t), ConfigType.JSON.getType());} finally {lock.unlock();}}
}

3.3 Nacos数据源整合到Sentinel中

  1. application.yml中需要对Nacos数据进行配置(以流控规则为例)
spring:application:name: sentinel-rule-push-demo  #微服务名称#配置nacos注册中心地址cloud:nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:# 添加sentinel的控制台地址dashboard: 127.0.0.1:8080datasource:flow-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-flowgroupId: SENTINEL_GROUP   # 注意groupId对应Sentinel Dashboard中的定义data-type: jsonrule-type: flow
  1. 将Nacos数据源注册为Sentinel的写数据源
public class NacosDataSourceListener implements ApplicationListener<ContextRefreshedEvent> {@Autowiredprivate SentinelProperties sentinelProperties;@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {// 1.获取流控规则数据源信息NacosDataSourceProperties nacosDataSourceProperties = sentinelProperties.getDatasource().get("flow-rules").getNacos();// 2.初始化流控规则数据源WritableDataSource<List<FlowRule>> writableDataSource = new NacosWritableDataSource<>(nacosDataSourceProperties.getServerAddr(), nacosDataSourceProperties.getGroupId(), nacosDataSourceProperties.getDataId(), JSON::toJSONString);// 将Nacos数据源注册为Sentinel写数据源WritableDataSourceRegistry.registerFlowDataSource(writableDataSource);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/16602.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

迷你手持小风扇哪个牌子质量好点?这五款迷你手持小风扇不要错过

随着空调的普及&#xff0c;我们对夏日热浪的抵抗力逐渐减弱。当从凉爽的空调屋步入闷热的户外、拥挤的交通工具或公共场所时&#xff0c;如何抵御热浪的侵袭成为大众关注的焦点。在这样的背景下&#xff0c;迷你手持小风扇凭借其便携性和即时降温功能&#xff0c;成为众多人的…

341_C++_使用C++中的std::map容器查找键的时候,注意给个默认值,防止成员函数value()未查找到键,确保即使键不存在,你也能安全地获取一个值

在C++中,std::map是一个关联容器,它存储的元素都是键值对(key-value pairs),并且按键(key)自动排序。 std::map有一个成员函数value(),它用于返回与给定键相关联的值。如果该键在map中不存在,则value()函数返回提供的默认值。 map<int, int> mKeyMaps; int ke…

降价!免费!AI大模型开启价格战,企业如何“薅”出绿色财富?

近期&#xff0c;国内大模型技术供应商之间的价格战&#xff0c;使得这项原本成本较高的技术变得更加亲民&#xff0c;极大降低了企业的技术采用门槛。这不仅为企业提供了经济实惠的技术解决方案&#xff0c;更为他们的绿色低碳转型之路带来了新的机遇。 随着全球气候变化问题…

MySQL -- 相关知识点

1.数据库相关介绍 数据库的选择通常取决于具体的应用需求&#xff0c;如性能、扩展性、数据一致性和易用性等因素。 1. 关系型数据库&#xff08;RDBMS&#xff09; MySQL&#xff1a; 广泛使用的开源数据库&#xff0c;支持大多数操作系统。强调易用性、灵活性和广泛的社区支…

基于Java+MySQL+Swing的学生管理系统

1.系统简介和开发背景 该同学工作积极主动、高效&#xff0c;学习认真&#xff0c;待人诚恳&#xff0c;能够做到服从指挥、认真听取老同志的指导&#xff0c;不怕苦、不怕累&#xff0c;表现有较强的求知欲&#xff0c;积极观察、体验、思考&#xff0c;并能够灵活运用自己的知…

自养号测评是什么?亚马逊、沃尔玛、Target卖家如何建立自己的护城河?

近期有跨境卖家咨询我自养买家账号测评的事情&#xff0c;他们还是有不了解自养号测评的&#xff0c;所以珑哥觉得有必要再讲一下卖家测评的一些事情&#xff0c;之前文章也说过。这可能是跨境卖家运营的一个趋势。今天珑哥着重来介绍一下自养号测评 一、什么叫做自养号测评&a…

OrangePi AIpro初体验之图片视频检测案例真实测评

OrangePi AIpro简介 OrangePi AIpro官网 Orange Pi AI Pro 开发板是香橙派联合华为精心打造的高性能AI 开发板&#xff0c;其搭载了昇腾AI 处理器&#xff0c;可提供8TOPS INT8 的计算能力&#xff0c;内存提供了8GB 和16GB两种版本。可以实现图像、视频等多种数据分析与推理…

简述v-for中的key的理解

在 Vue 中&#xff0c;v-for 是用来基于一个数组来渲染一个列表的指令。而 key 是一个特殊的属性&#xff0c;在 v-for 中经常被用到&#xff0c;它主要帮助 Vue 跟踪每个节点的身份&#xff0c;从而重用和重新排序现有元素。 key 的作用 性能优化&#xff1a;当 Vue 检测到列…

2024-python字典-报错compounds.iloc[0].molecule_structures.keys()

2024-python字典-报错compounds.iloc[0].molecule_structures.keys() .keys()拿不到 需要如何解决呢 import ast# 假设 "molecular_structures "是一个看起来像 Python 字典的字符串 molecule_structures df_VEGFR2_compounds.iloc[0].molecule_structures # 安全…

全球点赞最高的人颜廷利:真正的人生目标是什么

在那个充满生机的2024年春天&#xff0c;记者有幸对中国第一起名大师的老师颜廷利教授进行了深入的访谈。带着对其人生哲学的强烈好奇&#xff0c;记者紧张而期待地提出了问题&#xff1a;“颜教授&#xff0c;您在漫长的人生旅途中最追求的是什么&#xff1f;” 宁夏银川、山东…

PMP考试没有考过应该如何再考?

一、接受失败&#xff0c;理性分析 其实&#xff0c;PMP考试可以在PMI一年有效期内提交补考申请&#xff0c;若已经过了一年有效期&#xff0c;考生则需要重新进行完整的PMP考试报名流程。PMP考试补考费用&#xff1a;2500元/次。 1.接受失败&#xff1a;接受并处理情绪。面对…

【Python数据分析】基于自回归积分滑动平均模型的疫情分析报告 附完整python代码

资源地址&#xff1a;Python数据分析大作业 2000字 图文分析文档 疫情分析完整python代码 数据分析 数据来自法国疫情数据 资源地址&#xff1a;Python数据分析大作业 2000字 图文分析文档 疫情分析完整python代码 代码详解 完整代码文件 主要是对时间序列数据进行分析和预…

C++|四种方法解决三线程按顺序轮流打印ABC的问题:互斥锁和条件变量、原子操作、信号量

基于Pthreads线程库的实现 g your_program.cpp -lpthread编译时确保链接了Pthreads库. #include <pthread.h> #include <iostream> #include <unistd.h>// 全局变量&#xff0c;用于控制打印顺序 int turn 0; // 定义互斥锁和条件变量 pthread_mutex_t lo…

【#4 如何选择激活函数:深度学习中的关键决策】

文章目录 前言第一部分&#xff1a;激活函数的基础知识1.1 激活函数简介1.2 激活函数的作用 第二部分&#xff1a;选择激活函数的考虑因素2.1 网络层级2.2 任务类型2.3 训练稳定性2.4 计算效率2.5 网络深度 第三部分&#xff1a;流行激活函数的特点与应用场景3.1 Sigmoid3.2 Re…

技术面‍:前端代码是如何与服务器交互的

前言&#xff1a; 本篇文章主要是想讲解 .html 文件和 .CSS 文件在实际开发中和后端服务器交互最后上线的基础原理。 面向的人群&#x1f195;&#xff1a;是刚入行不久&#xff0c;且目前只会写前端业务代码而不清楚整个工作流的前端新人。我会从 0 开始一步一步带你理解整个…

QT打包命令的使用

QT打包命令的使用 windeployqt untitled1.exe windeployqt -qmldir C:\Users\unikinfo\Documents\UNIKINFO\untitled\YNMapDisplay YNMapDisplay.dll linuxdeployqt 程序文件 -qmldirqml源码路径 -appimage

大规模敏捷SA(Leading SAFe)证书是什么意思?如何报名,含金量高吗?

大规模敏捷SA(Leading SAFe)证书是什么意思&#xff1f; 常规的敏捷框架适用于中小型项目团队&#xff0c;而且不具有扩展性。基于常规的敏捷框架&#xff0c;SAFe定义了一个可扩展的敏捷框架模型&#xff0c;它适用于大型团队的合作开发&#xff0c;可以提高团队之间的协作性…

备份工具 - dd 命令

目录 一、命令格式 二、示例 1.备份文件 2.备份分区到文件 3.备份整个硬盘 4.备份分区到另一个分区 5.测试cpu、磁盘 一、命令格式 dd 复制文件 命令格式&#xff1a;dd if“输入文件” of“输出文件” bs“数据块” count“数量”参数&#xff1a;if&#xff1a; # 定…

【再探】设计模式—职责链模式、命令模式及迭代器模式

行为型设计模式研究系统在运行时对象之间的交互&#xff0c;进一步明确对象的职责。有职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式及访问模式共11种。 1 职责链模式 需求&#xff1a;1) 请求能被多…

如何使用golang自带工具对代码进行覆盖率测试

在 Go 语言中&#xff0c;测试代码覆盖率通常使用 go test 命令结合 -cover 和 -coverprofile 1. 基本代码覆盖率报告 在项目目录下运行以下命令 go test -cover这将在控制台输出一个代码覆盖率的百分比。但是&#xff0c;这种方式不会保存覆盖率数据&#xff08;可以指定目…