三步实现 Sentinel-Nacos 持久化

一、背景

版本:【Sentinel-1.8.6】
模式:【Push 模式】

参照官网介绍:生产环境下使用Sentinel ,规则管理及推送模式有以下3种模式:在这里插入图片描述
比较之后,目前微服务都使用了各种各样的配置中心,故采用Push 模式来进行持久化,这里也主要介绍集合 Nacos 的持久化。

二、流程结构图

在这里插入图片描述
实现思路说明:微服务中增加基于Nacos的写数据源(WritableDataSource),当 Sentinel Dashboard 配置发生变更,则利用 nacos 配置变更通知微服务更新本地缓存。

三、代码整合

1. 在微服务中引入依赖。
 <!--sentinel持久化 采用 Nacos 作为规则配置数据源-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
依赖缘由

(ps: 至于为何要引入这个依赖,在此做下展开说明,着急的同学请略过看)
可以看到这个依赖包的源码中只有一个类,那么这个类一定很重要了,看看它具体做了啥:
在这里插入图片描述
NacosDataSource 中构造方法如下,里面有个重要的东西: configListener,我们先记住红框框起来的地方。
在这里插入图片描述
看看具体的方法 initNacosListener();loadInitialConfig();

// 初始化 Nacos 监听器
private void initNacosListener() {
	try {
	    // 根据数据源配置信息初始化Nacos 的配置服务: configService 
		this.configService = NacosFactory.createConfigService(this.properties);
		// 添加配置监听器.
		configService.addListener(dataId, groupId, configListener);
	} catch (Exception e) {
		RecordLog.warn("[NacosDataSource] Error occurred when initializing Nacos data source", e);
		e.printStackTrace();
	}
}

// 加载Nacos 已有配置文件
private void loadInitialConfig() {
	try {
		T newValue = loadConfig();
		if (newValue == null) {
			RecordLog.warn("[NacosDataSource] WARN: initial config is null, you may have to check your data source");
		}
		getProperty().updateValue(newValue);
	} catch (Exception ex) {
		RecordLog.warn("[NacosDataSource] Error when loading initial config", ex);
	}
}

又由于 NacosDataSource 继承自 AbstractDataSource,故此处的 loadConfig() 方法是调用 com.alibaba.csp.sentinel.datasource.AbstractDataSource#loadConfig()

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

查看 readSource() 实现:跳转 NacosDataSource.readSource() 中:

@Override
public String readSource() throws Exception {
	if (configService == null) {
		throw new IllegalStateException("Nacos config service has not been initialized or error occurred");
	}
	// 原来是获取nacos 中的配置
	return configService.getConfig(dataId, groupId, DEFAULT_TIMEOUT);
}

综上查看,Nacos 已经实现了读取配置的代码,那么我们只需要实现写入部分以及相关的配置即可。

2. 自己实现 Nacos 写入代码
1.定义 NacosWritableDataSource

依据读取部分的代码实现,利用 nacoscom.alibaba.nacos.api.config.ConfigService#publishConfig(java.lang.String, java.lang.String, java.lang.String) 方法,既会修改持久化文件,也会同步到对应的微服务。代码如下:

public class NacosWritableDataSource<T> implements WritableDataSource<T> {

    private NacosDataSourceProperties nacosDataSourceProperties;
    private ConfigService configService;
    private final Converter<T, String> configEncoder;

    private final Lock lock = new ReentrantLock(true);

    public NacosWritableDataSource(NacosDataSourceProperties nacosDataSourceProperties, Converter<T, String> configEncoder) {
        this.nacosDataSourceProperties = nacosDataSourceProperties;
        this.configEncoder = configEncoder;
        // 初始化 Nacos configService
        initConfigService();
    }

    private void initConfigService(){
        try {
            this.configService = NacosFactory.createConfigService(buildProperties(nacosDataSourceProperties));
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }

    private Properties buildProperties(NacosDataSourceProperties nacosDataSourceProperties) {
        Properties properties = new Properties();
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getServerAddr())) {
            properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosDataSourceProperties.getServerAddr());
        } else {
            properties.setProperty(PropertyKeyConst.ACCESS_KEY, nacosDataSourceProperties.getAccessKey());
            properties.setProperty(PropertyKeyConst.SECRET_KEY, nacosDataSourceProperties.getSecretKey());
            properties.setProperty(PropertyKeyConst.ENDPOINT, nacosDataSourceProperties.getEndpoint());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getNamespace())) {
            properties.setProperty(PropertyKeyConst.NAMESPACE, nacosDataSourceProperties.getNamespace());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getUsername())) {
            properties.setProperty(PropertyKeyConst.USERNAME, nacosDataSourceProperties.getUsername());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getPassword())) {
            properties.setProperty(PropertyKeyConst.PASSWORD, nacosDataSourceProperties.getPassword());
        }
        return properties;
    }

    @Override
    public void write(T value) throws Exception {
        lock.lock();
        try {
           // 发布新配置
            configService.publishConfig(nacosDataSourceProperties.getDataId(), nacosDataSourceProperties.getGroupId(), this.configEncoder.convert(value), ConfigType.JSON.getType());
        } catch (Exception e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void close() throws Exception {

    }


}

上述只实现了数据配置更新与同步,我们还需要根据 Sentinel 的不用规则来区分具体是更新哪个文件,因此有下:

2.定义 SentinelNacosDataSourceHandler

public class SentinelNacosDataSourceHandler implements SmartInitializingSingleton {

    private final SentinelProperties sentinelProperties;

    public SentinelNacosDataSourceHandler(SentinelProperties sentinelProperties) {
        this.sentinelProperties = sentinelProperties;
    }
  //实现SmartInitializingSingleton 的接口后,当所有非懒加载的单例Bean 都初始化完成以后,Spring 的IOC 容器会调用该接口的 afterSingletonsInstantiated() 方法
    @Override
    public void afterSingletonsInstantiated() {
        sentinelProperties.getDatasource().values().forEach(this::registryWriter);
    }

    private void registryWriter(DataSourcePropertiesConfiguration dataSourceProperties) {
        final NacosDataSourceProperties nacosDataSourceProperties = dataSourceProperties.getNacos();
        if (nacosDataSourceProperties == null) {
            return;
        }
        final RuleType ruleType = nacosDataSourceProperties.getRuleType();
        // 通过数据源配置的 ruleType 来注册数据源
        switch (ruleType) {
            case FLOW:
                WritableDataSource<List<FlowRule>> flowRuleWriter = new NacosWritableDataSource<>(nacosDataSourceProperties, JSON::toJSONString);
                WritableDataSourceRegistry.registerFlowDataSource(flowRuleWriter);
                break;
            case DEGRADE:
                WritableDataSource<List<DegradeRule>> degradeRuleWriter = new NacosWritableDataSource<>(nacosDataSourceProperties, JSON::toJSONString);
                WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWriter);
                break;
            case PARAM_FLOW:
                WritableDataSource<List<ParamFlowRule>> paramFlowRuleWriter = new NacosWritableDataSource<>(nacosDataSourceProperties, JSON::toJSONString);
                ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWriter);
                break;
            case SYSTEM:
                WritableDataSource<List<SystemRule>> systemRuleWriter = new NacosWritableDataSource<>(nacosDataSourceProperties, JSON::toJSONString);
                WritableDataSourceRegistry.registerSystemDataSource(systemRuleWriter);
                break;
            case AUTHORITY:
                WritableDataSource<List<AuthorityRule>> authRuleWriter = new NacosWritableDataSource<>(nacosDataSourceProperties, JSON::toJSONString);
                WritableDataSourceRegistry.registerAuthorityDataSource(authRuleWriter);
                break;
            default:
                break;
        }
    }
}
3. Spring IOC 管理 SentinelNacosDataSourceHandler
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(SentinelAutoConfiguration.class)
public class SentinelNacosDataSourceConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public SentinelNacosDataSourceHandler sentinelNacosDataSourceHandler(SentinelProperties sentinelProperties){
        return new SentinelNacosDataSourceHandler(sentinelProperties);
    }

}

4. 配置文件

bootstrap.yml 中的配置文件内容如下:

spring:
  application:
    name: spring-cloud-sentinel-demo  #微服务名称
  cloud:
    nacos:
      config:  #配置nacos配置中心地址
        server-addr: 192.168.0.123:8847
        username: nacos
        password: nacos
        file-extension: yml   # 指定配置文件的扩展名为yml
        namespace: 6a7dbc5f-b376-41c6-a282-74ad4fd4829b

nacos 中微服务对应的配置文件内容如下:(也就是 application.yml ):

server:
  port: 8800

spring:
  application:
    name: spring-cloud-sentinel-demo  #微服务名称

  cloud:
    nacos:  #配置nacos注册中心地址
      discovery:
        server-addr: 192.168.0.123:8847
        username: nacos
        password: nacos
		
    sentinel:
      transport:
        dashboard: 192.168.0.123:8091
      datasource:
        flow-rules: #流控规则
          nacos:
            server-addr: 192.168.0.123:8847
            namespace: 6a7dbc5f-b376-41c6-a282-74ad4fd4829b
            username: nacos
            password: nacos
            dataId: ${spring.application.name}-flow-rules
            groupId: SENTINEL_GROUP   # 注意groupId对应Sentinel Dashboard中的定义
            data-type: json
            rule-type: flow
        degrade-rules: #降级规则
          nacos:
            server-addr: 192.168.0.123:8847
            namespace: 6a7dbc5f-b376-41c6-a282-74ad4fd4829b
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: degrade
        param-flow-rules:
          nacos:
            server-addr: 192.168.0.123:8847
            namespace: 6a7dbc5f-b376-41c6-a282-74ad4fd4829b
            dataId: ${spring.application.name}-param-flow-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: param-flow
        authority-rules:
          nacos:
            server-addr: 192.168.0.123:8847
            namespace: 6a7dbc5f-b376-41c6-a282-74ad4fd4829b
            dataId: ${spring.application.name}-authority-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: authority
        system-rules:
          nacos:
            server-addr: 192.168.0.123:8847
            namespace: 6a7dbc5f-b376-41c6-a282-74ad4fd4829b
            dataId: ${spring.application.name}-system-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: system

3. 测试
1. 在 Sentinel Dashboard 新建流控规则:

在这里插入图片描述
查看 Nacos 配置中心,在对应的 namespace 下多了一个配置文件:spring-cloud-sentinel-demo-flow-rules 因为在上述文件中指定了 flow-rules 数据源的 namespacegroup
在这里插入图片描述查看此配置文件的详情可以看到:内容就是刚才流控规则的序列化内容:
在这里插入图片描述
综上,Sentinel Dashboard 新建的规则可以成功序列化到 Nacos 的配置中。

2. 在 Nacos 控制台修改对应的 count,在Sentinel Dashboard 查看是否同步显示:

修改前先查看Sentinel Dashboard 目前流控的阈值为2:
在这里插入图片描述
修改Nacos 中 spring-cloud-sentinel-demo-flow-rules 的配置,并发布:
在这里插入图片描述
修改后查看 Sentinel Dashboard 目前流控的阈值为3:
在这里插入图片描述
测试流控效果,已可以正常限流:
在这里插入图片描述

4. 其他规则也类似于流控规则

四、总结

最后附上这部分源码梳理图,可以结合上述内容一起理解。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5 虚幻游戏报错常用解决方法(幻兽帕鲁UE5报错)

在体验使用虚幻引擎5、4&#xff08;UE5/UE4&#xff09;开发的游戏如《幻兽帕鲁》时&#xff0c;玩家可能会遇到各种报错情况&#xff0c;例如黑屏、闪退、C运行时错误等。本博客将汇集一系列有效解决方案&#xff0c;通过调整虚幻引擎内置命令行参数以及优化系统环境&#xf…

mysql 批量查询取每一组最新一条数据

AI回答 需求 根据车牌号查询最新的一条交车记录的‘合同号’ &#xff0c;与上面需要类似&#xff0c;这里只需要查询‘合同号’这个字段 方式1 直接把需要查询的字段加上contract_no&#xff0c;直接查&#xff0c;不用子查询 SELECT number_plate,id,contract_no, MAX( …

K8S-NFS-StorageClass

工作流程 K8s中部署NFS-StorageClass K8s的StorageClass提供了为集群动态创建PV的能力。 1.部署NFS服务 2.选择NFS的Provinisoner驱动 K8S中没有内置的NFS的制备器&#xff0c;而定义StorageClass的时候需要指定制备器&#xff08;Pervisioner&#xff09;,所以需要&#xf…

EtherCAT转ModbusTCP网关

一、功能概述 1.1设备简介 本产品是EtherCAT和Modbus TCP网关&#xff0c;使用数据映射方式工作。 本产品在EtherCAT侧作为EtherCAT从站&#xff0c;接TwinCAT、CodeSYS、PLC等&#xff1b;在ModbusTCP侧做为ModbusTCP主站&#xff08;Client&#xff09;或从站&#xff08;…

Windows - 防火墙 - 如何开启单个端口以供Web应用访问(以82端口为例) - 开启端口后还是访问失败了?

Windows - 防火墙 - 如何开启单个端口以供Web应用访问(以82端口为例) - 开启端口后还是访问失败了&#xff1f; 前言 在网上搜“防火墙开启某个端口”供其他机器访问&#xff0c;都是只讲到了“如何允许某个端口被访问”&#xff0c;而没有后续了。 我之前就遇到过这个问题&…

寒假用它练脑子!和AI大战几百回合,锻炼思维逻辑、专注力~

棋类游戏&#xff0c;永远是锻炼思维能力的优选。 下棋对于孩子的成长有诸多好处&#xff0c;比如会让孩子静下心来&#xff0c;锻炼洞察力和专注力。生死对决与全盘的计算&#xff0c;促使思维力扩展。棋盘上的设计和构筑&#xff0c;丰富孩子的想象力等等。 下棋过程中大量的…

docker集成 nacos/nacos-server (包括踩的坑)

tips 这边需要的数据库我已经安装好了&#xff0c;所以数据库的安装这边已经省略了 拉取镜像&#xff08;这边使用nacos1.4.1作为例子&#xff09; docker pull nacos/nacos-server:1.4.1创建映射的文件夹 (conf存放配置文件&#xff0c;logs存放日志文件) mkdir -p /data/n…

【EI会议征稿通知】2024年生成式人工智能与信息安全国际学术会议(GAIIS 2024)

2024年生成式人工智能与信息安全国际学术会议&#xff08;GAIIS 2024&#xff09; 2024 International Conference on Generative Artificial Intelligence and Information Security 2024年生成式人工智能与信息安全国际学术会议&#xff08;GAIIS 2024&#xff09;将于 202…

【机器学习】基于K-近邻的车牌号识别

实验四: 基于K-近邻的车牌号识别 1 案例简介 ​ 图像的智能处理一直是人工智能领域广受关注的一类技术&#xff0c;代表性的如人脸识别与 CT 肿瘤识别&#xff0c;在人工智能落地的进程中发挥着重要作用。其中车牌号识别作为一个早期应用场景&#xff0c;已经融入日常生活中&…

【Web前端笔记06】CSS常用属性

目录 一、字体属性 1、color 字体颜色 2、font-size 字体大小&#xff08;默认16px) 3、font-weight 文本粗细 4、font-style 字体样式 5、font-family 指定一个元素的字体 二、背景属性 1、background-color 背景颜色 2、background-image: url("img/do.png"); 背景…

Linux-485接口

接口引脚定义 2线485通信方法 在 2 线制 RS-485 中&#xff0c;设备之间共享一条数据线&#xff08;D 和 D-&#xff09;&#xff0c;因此需要一种机制来区分哪个设备正在发送数据&#xff0c;哪个设备处于接收状态。 对于这种情况&#xff0c;常用的方法是在总线上使用一个控…

双目视觉目标追踪及三维坐标获取—python(代码)

2022年九月更新&#xff1a; 在原来的基础上&#xff0c;我使用了yolov5代替了opencv的目标检测算法辅助相机进行三维坐标的获取&#xff0c;并成功用获取的坐标实时控制机械臂&#xff0c;感兴趣的话可以看我b站里的视频&#xff0c;视频下方也有开源的链接&#xff1a;【软核…

【教程】Objective-C 性能监控

1、内存监控 CPU内存监控 克魔助手提供了分析内存占用、查看 CPU 实时活动数据以及追踪特定应用程序的功能&#xff0c;让开发者可以更好地了解应用程序的运行情况。 以下是一些示例截图&#xff1a; 同样&#xff0c;克魔助手还提供了内存、GPU 性能监控、网络监控等功能&am…

什么是接口的幂等性,如何保证接口的幂等性?

✅作者简介&#xff1a;大家好&#xff0c;我是Leo哥&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo哥的博客 &#x1f49e;当前专栏&#xff1a; Java ✨特色专栏&#xff1a; MyS…

springcloud bus消息总线

简介 Spring Cloud Bus 配合Spring Cloud Config 使用可以实现配置的动态刷新。 Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架&#xff0c;它整合了Java的事件处理机制和消息中间件的功能。Spring Clud Bus目前支持RabbitMQ和Kafka。 Spring C…

K-means 算法的原理简介

K-means 是数据科学和商业的基本算法。只需 4 分钟即可了解需要 4 周时间才弄清楚的内容。让我们深入了解一下。 1. K-means是一种流行的用于聚类的无监督机器学习算法。它是用于客户细分、库存分类、市场细分甚至异常检测的核心算法。 2. 无监督&#xff1a;K-means 是一种无…

循环神经网络RNN专题(01/6)

一、说明 RNN用于处理序列数据。在传统的神经网络模型中&#xff0c;是从输入层到隐含层再到输出层&#xff0c;层与层之间是全连接的&#xff0c;每层之间的节点是无连接的。但是这种普通的神经网络对于很多问题却无能无力。例如&#xff0c;你要预测句子的下一个单词是什么&a…

SimpleDateFormat 格式化 Date 时间戳

前言 Date 是 Java 中经常用来表示时间的类型&#xff0c;但将 Date 类型的数据发送给前端时&#xff0c;通常会呈现出乱码的状态&#xff0c;用户不宜理解&#xff0c;所以要通过 SimpleDateFormat 把 Date 类型的数据格式化为用户容易理解的格式 如下是 Date 的格式&#xff…

算法模板 3.二分查找

二分查找 789. 数的范围 - AcWing题库 check函数&#xff08;lr&#xff08;这里要不要1&#xff09;&#xff09;>> 1 &#xff0c;要根据具体情况&#xff0c;如果是r mid的话lr就不用1&#xff0c;l mid的话就要1 #include <bits/stdc.h> using namespace s…

TikTok赚钱又有新路子?TikTok选品有什么新秘籍?做对什么才能GMV破千万刀?

这一年&#xff0c;到底发生了什么&#xff1f; 上半年TikTok面临北美的严格审查和信息安全方面的质疑&#xff0c;但总算在9月有惊无险地打开了北美TikTok Shop这个“金匣子”&#xff0c;给跨境电商赛道带来新的增量机会&#xff0c;而东南亚市场虽在短暂停滞后迅速峰回路转…
最新文章