Sentinel Dashboard 规则联动持久化方案

一、Sentinel Dashboard 规则联动持久化方案

Sentinel 是阿里开源的一个流量控制组件,它提供了一种流量控制、熔断降级、系统负载保护等功能的解决方案。并且我们通过 Sentinel Dashboard 可以非常便捷的添加或修改规则策略,但是如果细心的小伙伴应该可以发现,默认情况下通过 Sentinel Dashboard 添加或修改的规则并没有进行持久化,服务重启后先前的规则也就消失了,这对于生产环境肯定是不允许的,那如何进行持久化操作呢?

Sentinel 官方已经提供了几种持久化方案,比如可以将规则存放在 Nacos、Redis、ZK、Apollo 等等,但是这些操作都没有和 Sentinel Dashboard 做联动,我们需要手动编写规则,如 json 格式,存放在持久化引擎中。

这里我以 Nacos 为例,通过添加 sentinel-datasource-nacos 依赖可以将配置持久化到 Nacos 配置引擎中:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

比如我们将如下配置在 Nacos 中:

[
 {
 "resource": "mylimit",
 "controlBehavior": 0,
 "count": 1.0,
 "grade": 1,
 "limitApp": "default",
 "strategy": 0
 }
]

在这里插入图片描述

此时可以在 Sentinel Dashboard 中看到该规则:

在这里插入图片描述

但是返回来在 Sentinel Dashboard 添加或修改的规则并没有反向持久化到 Nacos 中,并且随着服务的重启修改的规则会丢失。

在这里插入图片描述

在这里插入图片描述

因此解决上述问题,可以从两个方向入手,一个是拉模式、一个是推模式:

  • 拉模式:通过 sentinel-datasource-extension 包,扩展读数据源RefreshableDataSource,定期扫描目标数据源,比如服务器下的某个文件,如果发生变动便加载到内存中。以及写数据源 WritableDataSource ,当在 Sentinel Dashboard 中变动规则时 ,由服务同步将规则持久化到数据源中。

在这里插入图片描述

  • 推模式:服务通过监有事件通知能力的目标数据源,如 nacos、redis、zk、Apollo 等,当目标数据源中的规则发生变动时,通过事件监听通知服务更新规则,而 Sentinel Dashboard 则不直接将规则发往服务,而是主动持久化到目标数据源中。这种方式需要修改 Sentinel Dashboard 的源码,将原先的通知逻辑修改为存储到目标数据源。

在这里插入图片描述

两种方式都有各自的优缺点,例如 拉模式 下,如果主动改动数据源的数据,需要等到下次扫描时才能生效,而 推模式 由于采用事件监听的方式,可以保证修改的实时性。但是 拉模式 下无需修改源码,在官方提供的依赖基础上就可以实现,而推模式 需要根据源码定制化开发需求。

下面一起实践下两种方案。

为了方便后续的测试,这里提前创建一个接口,指定资源名称为 r1

@RestController
@RequestMapping("/test")
public class TestController {

    @SentinelResource(value = "r1",
            blockHandler = "blockHandler")
    @GetMapping("/t1")
    public String t1(){
        return "success";
    }

    public String blockHandler(BlockException exception){
        return "降级了!!!!";
    }

}

二、拉模式

首先需要引入 sentinel-datasource-extension 依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-extension</artifactId>
</dependency>

这里使用本地文件的方式存储规则,也是 extension 依赖中已经实现好的方式,如果需要存储到其他数据源中,可以模仿 FileRefreshableDataSource 以及 FileWritableDataSource 进行修改。并且还需要实现 InitFunc接口,在init方法中指定DataSource初始化逻辑,并利用spi机制实现加载。

对于规则 Sentinel 中有多种类型,这里实现了 流量、熔断、权限、系统 四个方面的规则持久化:

public class FileDataSourceInit implements InitFunc {
    /**
     * 规则文件
     */
    private static final String RULE_FILE_PATH = System.getProperty("user.dir") + File.separator;
    private static final String FLOW_RULE_FILE_NAME = "FlowRule.json";
    private static final String DEGRADE_RULE_FILE_NAME = "DegradeRule.json";
    private static final String AUTHORITY_RULE_FILE_NAME = "AuthorityRule.json";
    private static final String SYSTEM_RULE_FILE_NAME = "SystemRule.json";

    @Override
    public void init() throws Exception {
        disposeRules();
    }

    private void disposeRules() throws FileNotFoundException {
        String flowRuleFilePath = RULE_FILE_PATH + FLOW_RULE_FILE_NAME;
        String degradeRuleFilePath = DEGRADE_RULE_FILE_NAME + FLOW_RULE_FILE_NAME;
        String authorityRuleFilePath = AUTHORITY_RULE_FILE_NAME + FLOW_RULE_FILE_NAME;
        String systemRuleFilePath = SYSTEM_RULE_FILE_NAME + FLOW_RULE_FILE_NAME;

        FileRefreshableDataSource<List<FlowRule>> flowRuleRead = new FileRefreshableDataSource<>(
                flowRuleFilePath, source -> JSON.parseObject((String) source,
                new TypeReference<List<FlowRule>>() {
                })
        );

        FileRefreshableDataSource<List<DegradeRule>> degradeRuleRead = new FileRefreshableDataSource<>(
                degradeRuleFilePath, source -> JSON.parseObject((String) source,
                new TypeReference<List<DegradeRule>>() {
                })
        );

        FileRefreshableDataSource<List<AuthorityRule>> authorityRuleRead = new FileRefreshableDataSource<>(
                authorityRuleFilePath, source -> JSON.parseObject((String) source,
                new TypeReference<List<AuthorityRule>>() {
                })
        );

        FileRefreshableDataSource<List<SystemRule>> systemRuleRead = new FileRefreshableDataSource<>(
                systemRuleFilePath, source -> JSON.parseObject((String) source,
                new TypeReference<List<SystemRule>>() {
                })
        );

        FlowRuleManager.register2Property(flowRuleRead.getProperty());
        DegradeRuleManager.register2Property(degradeRuleRead.getProperty());
        SystemRuleManager.register2Property(systemRuleRead.getProperty());
        AuthorityRuleManager.register2Property(authorityRuleRead.getProperty());


        WritableDataSource<List<FlowRule>> flowRuleData = new FileWritableDataSource<>(
                flowRuleFilePath, this::encodeJson
        );

        WritableDataSource<List<DegradeRule>> degradeRuleData = new FileWritableDataSource<>(
                degradeRuleFilePath, this::encodeJson
        );

        WritableDataSource<List<AuthorityRule>> authorityRuleData = new FileWritableDataSource<>(
                authorityRuleFilePath, this::encodeJson
        );

        WritableDataSource<List<SystemRule>> systemRuleData = new FileWritableDataSource<>(
                systemRuleFilePath, this::encodeJson
        );

        WritableDataSourceRegistry.registerFlowDataSource(flowRuleData);
        WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleData);
        WritableDataSourceRegistry.registerSystemDataSource(systemRuleData);
        WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleData);
    }


    private <T> String encodeJson(T t) {
        return JSON.toJSONString(t);
    }

}

然后在 resources 下,创建 META-INF.services 包,然后在该包下新建 com.alibaba.csp.sentinel.init.InitFunc 文件,文件的内容就是上面类的完整包名地址:

在这里插入图片描述

然后启动项目,在 Sentinel Dashboard 中添加一个规则:

在这里插入图片描述

可以在项目根目录发现已经创建了 FlowRule.json 文件,并且存储的内容就是 JSON 格式的规则信息:

在这里插入图片描述

如果此时将服务重启,再次查看 Sentinel Dashboard 可以发现原有的规则依然存在。

并且多次访问 t1 测试接口,可以看到规则依然有效:

在这里插入图片描述

三、推模式

推模式下可以通过事件监听更及时的通知到目标服务,这里采用 Nacos 作为目标数据源进行实验。上面实验拉模式可以感觉出 Sentinel 不同类型的规则是单独控制的,这里为了方便演示,以流量规则的修改为例进行实践。

同时做好Nacos中配置文件名的约定为 {application name}-sentinel-{type},例如:这里的实验项目名称为 sentinel-demo 的流量规则的名字为:sentinel-demo-sentinel-flow

Nacos 中创建目标配置:

在这里插入图片描述

然后在目标服务中配置flow规则指向该配置:

在这里插入图片描述

上面提到推模式需要修改源码,这里先将 Sentinel 的源码拉取下来:

git clone https://github.com/alibaba/Sentinel.git

使用 IDEA 打开项目,其中 sentinel-dashboard 就是下面我们需要修改的项目:

在这里插入图片描述

Sentinel1.4.0开始,sentinel-dashboard项目就提供了 DynamicRulePublisherDynamicRuleProvider 两个接口用于实现自定义的规则推送和拉取操作,因此我们后续的操作也是基于这两个接口:

在这里插入图片描述

首先在该项目中加入 nacos-client 的依赖:

<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>1.4.2</version>
</dependency>

先实现一个 RuleNacosConfig 类,用来定义和 Nacos 的约定信息,以及声明出 ConfigService

@Configuration
public class RuleNacosConfig {
    /**
     * Nacos 配置所在组
     */
    public static final String GROUP_ID = "DEFAULT_GROUP";
    /**
     * Nacos 流量规则的名称后缀
     */
    public static final String FLOW_DATA_ID_POSTFIX = "-sentinel-flow";

    /**
     *  Nacos 信息, 最好读取配置信息,这里演示,先写死
     */
    @Bean
    public ConfigService nacosConfigService() throws Exception {
        return ConfigFactory.createConfigService("127.0.0.1:8848");
    }
}

实现 DynamicRuleProvider ,根据不同的服务从 Nacos 中拉取配置:

@Component("flowRuleNacosProvider")
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {

    @Autowired
    private ConfigService configService;

    @Override
    public List<FlowRuleEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + RuleNacosConfig.FLOW_DATA_ID_POSTFIX,
                RuleNacosConfig.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return JSON.parseArray(rules, FlowRuleEntity.class);
    }
}

然后实现 DynamicRulePublisher ,将修改后的规则持久化到 Nacos

@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {

    @Autowired
    private ConfigService configService;

    @Override
    public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
        if (StringUtils.isBlank(app)) {
            throw new RuntimeException("Server app is null!");
        }
        if (rules == null) {
            return;
        }
        configService.publishConfig(app + RuleNacosConfig.FLOW_DATA_ID_POSTFIX,
                RuleNacosConfig.GROUP_ID, JSON.toJSONString(rules));
    }
}

接着修改 com.alibaba.csp.sentinel.dashboard.controller.FlowControllerV1 类,先将上面创建的 FlowRuleNacosProviderFlowRuleNacosPublisher 注入进来:

在这里插入图片描述

下面需要修改 /rules/rule 两个接口,使用上面我们自定义逻辑,首先在 /rules 接口中,注释掉原来的 sentinelApiClient.fetchFlowRuleOfMachine ,替换成:

List<FlowRuleEntity> rules = flowRuleNacosProvider.getRules(app);

在这里插入图片描述

然后在 /rule 接口,注释掉 publishRules 方法的调用,换成:

flowRuleNacosPublisher.publish(entity.getApp(), repository.findAllByApp(entity.getApp()));

在这里插入图片描述

停止掉原有的 Sentinel Dashboard 控制台服务,然后本地启动新的 Sentinel Dashboard 服务,或者打包成 jar 包后启动 。

浏览器访问新的 Sentinel Dashboard 控制台。

这里测试增加一个流控规则:

在这里插入图片描述

下面查看 Nacos 中对应的配置内容:

在这里插入图片描述

已经主动持久化到 Nacos 中了,并且多次访问测试接口,规则也依然生效:

在这里插入图片描述

到此整个修改过程就结束了,虽然上面仅针对流量控制进行了整合,其他模式也是一样的处理方式,有兴趣的小伙伴可以继续补充完善。

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

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

相关文章

redis6.2.7安装

1、下载上传到服务器 从官下载redis&#xff0c;地址 https://redis.io/download/#redis-downloads 然后上传到服务器目录 app/apps目录下 2、安装gcc编译器 使用gcc --version命令测试是否已经安装了gcc编译环境&#xff0c;如果没有安装执行以下命令安装 yum install -y …

定积分求解过程是否变限问题 以及当换元时注意事项

目录 定积分求解过程是否变限问题 文字理解&#xff1a; 实例理解&#xff1a; 易错点和易混点&#xff1a; 1&#xff1a;定积分中的换元指什么&#xff1f; 2&#xff1a; 不定积分中第一类换元法和第二类换元法的本质和区别 3&#xff1a; df(x) ----> df(x)这…

c++(一)

c&#xff08;一&#xff09; C与C有什么区别命名空间使用 输入输出流引用指针和引用的区别定义拓展 函数重载例子测试函数重载原理 参数默认值什么是参数默认值注意 在c中如何引入c的库动态内存分配new、delete与malloc、free的区别&#xff1f; C与C有什么区别 <1>都是…

【高数】重点内容,公式+推导+例题,大学考试必看

目录 1 隐函数求导1.1 公式1.2 说明1.3 例题 2 无条件极值2.1 运用2.2 求解2.3 例题 3 条件极值3.1 运用3.2 求解3.3 例题 4 二重积分4.1 直角坐标下4.2 极坐标下4.3 例题 5 曲线积分5.1 第一型曲线积分5.2 第二型曲线积分5.3 例题 6 格林公式6.1 公式6.2 说明6.3 例题 &#x…

C++课程设计:学校人员信息管理系统(可视化界面)

目录 学校人员信息管理系统 操作演示 MP4转GIF动图 设计功能要求 评分标准 QT Creator安装和新建项目 QT安装 QT新建项目 管理系统程序设计 mainwindow.h 文件 mainwindow.h 程序释义 mainwindow.cpp 文件 mainwindow.cpp 程序释义 main.h 文件 TXT文件生成 博主…

Java进阶学习笔记12——final、常量

final关键字&#xff1a; final是最终的意思。可以修饰类、方法、变量。 修饰类&#xff1a;该类就被称为最终类&#xff0c;特点是不能被继承了。 修饰方法&#xff1a;该方法是最终方法&#xff0c;特点是不能被重写了。 修饰变量&#xff1a;该变量只能被赋值一次。 有些…

[书生·浦语大模型实战营]——第三节:茴香豆:搭建你的 RAG 智能助理

0.RAG 概述 定义&#xff1a;RAG&#xff08;Retrieval Augmented Generation&#xff09;技术&#xff0c;通过检索与用户输入相关的信息片段&#xff0c;并结合外部知识库来生成更准确、更丰富的回答。解决 LLMs 在处理知识密集型任务时可能遇到的挑战, 如幻觉、知识过时和缺…

栈的实现(C语言)

文章目录 前言1.栈的概念及结构2.栈的实现3.具体操作3.1.初始化栈(StackInit)和销毁栈(StackDestory)3.2.入栈(StackPush)和出栈(StackPop)3.3.获得栈的个数(StackSize)、获得栈顶元素(StackTop)以及判空(StackEmpty) 前言 前段时间我们学习过了链表和顺序表等相关操作&#x…

【全网最全】2024电工杯数学建模A题54页A题保奖成品论文+配套代码

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片链接&#xff0c;那是获取资料的入口&#xff01; 【全网最全】2024电工杯数学建模A题成品论文前三题完整解答matlabpy代码等&#xff08;后续会更新成品论文&#xff09;「首先来看看目前已有的资料&am…

《Ai学习笔记》自然语言处理 (Natural Language Processing):机器阅读理解-基础概念解析01

自然语言处理 (Natural Language Processing)&#xff1a; NLP四大基本任务 序列标注&#xff1a; 分词、词性标注 分类任务&#xff1a; 文本分类、情感分析 句子关系&#xff1a;问答系统、对话系统 生成任务&#xff1a;机器翻译、文章摘要 机器阅读理解的定义 Machi…

用LabVIEW进行CAN通信开发流程

本文详细介绍了在LabVIEW中开发CAN&#xff08;Controller Area Network&#xff09;通信的流程&#xff0c;包括硬件配置、软件编程和调试步骤。重点讨论了开发过程中需要注意的问题&#xff0c;如节点配置、数据帧格式和错误处理等&#xff0c;为开发高效可靠的CAN通信应用提…

[C++]debug介绍+debug时如何查看指针指向内存处的值

一、简介 预备工具和知识&#xff1a;使用使用VSCode使用Debug。 本文简介&#xff1a;本文将简要介绍debug中Continue&#xff0c;Step Over&#xff0c;Step Into和Restart的功能。并介绍如何在debug时查看动态内存地址&#xff08;指针&#xff09;的值&#xff1b; 二、D…

npm 错误,ERESOLVE unable to resolve dependency tree

npm 错误,ERESOLVE unable to resolve dependency tree 在命令中增加 --legacy-peer-dep 选项或者–force npm install --legacy-peer-depsnpm install --force

Mysql 找出未提交事务的SQL及死锁

未提交事务&#xff1a; 通过查看information_schema.INNODB_TRX视图,您可以了解当前系统中正在运行的事务情况,从而进行问题排查和性能优化。 SELECT * FROM information_schema.innodb_trx; 通过trx_state为RUNNIG,trx_started判断是否有一直RUNNING的事务。 如果有未提交…

MySQL 8.4.0 LTS 变更解析:I_S 表、权限、关键字和客户端

↑ 关注“少安事务所”公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ MySQL 8.4.0 LTS 已经发布 &#xff0c;作为发版模型变更后的第一个长期支持版本&#xff0c;注定要承担未来生产环境的重任&#xff0c;那么这个版本都有哪些新特性、变更&#xff0c;接下来少…

企业如何正确地利用LLM大模型?

大型语言模型 (LLM) 不值得信任。就是这样。 考虑到它们先进的 AI 能力以及当今强大的基础模型的普遍知识&#xff0c;这似乎是一件令人惊讶的事情。然而&#xff0c;问题的关键在于 LLM 无法解释其输出。你不能信任 LLM 的结果&#xff0c;不是因为它不准确&#xff0c;而是因…

如何解决mfc110udll丢失的问题,7个方法可解决mfc110udll丢失

mfc110u.dll是一个动态链接库文件&#xff0c;属于Microsoft Visual C 2012 Redistributable Package的一部分。它是Microsoft Foundation Classes (MFC) 库的一个版本&#xff0c;专门用于支持基于MFC开发的应用程序运行。MFC是一个用于Windows操作系统上使用C进行本机应用程序…

[书生·浦语大模型实战营]——第二节:轻松玩转书生·浦语大模型趣味 Demo

1. 部署InternLM2-Chat-1.8B 模型进行智能对话 1.1配置环境 创建开发机 Intern Studio 官网网址&#xff1a;https://studio.intern-ai.org.cn/ 进入官网后&#xff0c;选择创建开发机&#xff0c;填写 开发机名称 后&#xff0c;点击 选择镜像 使用 Cuda11.7-conda 镜像&am…

JVM堆分配中TLAB分配方案

个人博客 JVM堆分配中TLAB分配方案 | iwts’s blog Java对象的内存分配过程如何保证线程安全 对象的内存分配过程中&#xff0c;主要流程是将对象的引用指向一个具体的内存区域&#xff0c;然后进行初始化操作。 但是&#xff0c;因为堆是全局共享的&#xff0c;因此在同一…

自建公式,VBA在Excel中轻松获取反义词

自建公式&#xff0c;VBA在Excel中轻松获取反义词 文章目录 前言一、爬取网站数据二、代码1.创建数据发送及返回方法2.汉字转UTF8编码2.获取反义词 三、运行效果截图 前言 小学语文中&#xff0c;近义词、反义词是必考内容之一。家长不能随时辅导怎么办&#xff1f;有VBA&…