Sentinel Dashboard 规则联动持久化方案

news2024/11/17 15:59:00

一、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 中了,并且多次访问测试接口,规则也依然生效:

在这里插入图片描述

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

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

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

相关文章

C++语言·list链表

其实现在在讲这些容器的时候&#xff0c;我们的重点已经不是它的接口都有什么&#xff0c;功能都是什么了&#xff0c;这些内容官网上都能查到&#xff0c;而且容器和容器之间接口的不同处很少&#xff0c;我在讲解的话也只是把官网上的东西截图下来复述一下。现在的重点其实都…

【知识图谱】探索攻略:基础、构建、高级应用与相关论文方向

【知识图谱】相关文章汇总 写在最前面一、什么是知识图谱&#xff1f;二、相关历史文章代码实现&#xff1a;简单的知识图谱可视化知识图谱前身&#xff1a;信息抽取知识图谱应用1&#xff1a;社交网络分析知识图谱应用2&#xff1a;威胁情报挖掘知识图谱应用3&#xff1a;Code…

⌈ 传知代码 ⌋ 实现沉浸式交互故事体验

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

DNS服务的部署与配置(2)

1、dns的安装及开启 dnf install bind.x86_64 -y #安装 #Berkeley Internet Name Domain (BIND) systemctl enable --now named #启用dns服务&#xff0c;服务名称叫named firewall-cmd --permanent --add-servicedns #火墙设置 firewall-cmd --reload …

Linux(三)

Linux&#xff08;三&#xff09; Linux网络配置管理网络基础知识 IP地址A类 由1个字节网络地址3个字节主机地址B类 由2个字节网络地址2个主机地址C类 由3个字节网络地址1个主机地址D类:主要用于组播E类:为将来使用保留 子网掩码子网掩码作用网关DNS服务器 Linux用户管理用户的…

服务器数据恢复—同友存储raid5阵列上层虚拟机数据恢复案例

服务器数据恢复环境&#xff1a; 某市教育局同友存储&#xff0c;存储中有一组由数块磁盘组建的raid5阵列&#xff0c;存储空间划分若干lun。每个lun中有若干台虚拟机&#xff0c;其中有数台linux操作系统的虚拟机为重要数据。 存储结构&#xff1a; 服务器故障&#xff1a; r…

Linux之LLVM、Clang、Clang++区别及用法实例(六十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Java 异步编程——Java内置线程调度器(Executor 框架)

文章目录 Java多线程的两级调度模型Executor 框架Executor 框架的组成概念Executor 框架中任务执行的两个阶段&#xff1a;任务提交和任务执行 在 Java1.5 以前&#xff0c;开发者必须手动实现自己的线程池&#xff1b;从 Java1.5 开始&#xff0c;Java 内部提供了线程池。 在J…

concurrency 并行编程

Goroutine go语言的魅力所在&#xff0c;高并发。 线程是操作系统调度的一种执行路径&#xff0c;用于在处理器执行我们在函数中编写的代码。一个进程从一个线程开始&#xff0c;即主线程&#xff0c;当该线程终止时&#xff0c;进程终止。这是因为主线程是应用程序的原点。然后…

LeetCode题练习与总结:二叉树的层序遍历Ⅱ--107

一、题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[…

springboot3微服务下结合springsecurity的认证授权实现

1. 简介 在微服务架构中&#xff0c;系统被拆分成许多小型、独立的服务&#xff0c;每个服务负责一个功能模块。这种架构风格带来了一系列的优势&#xff0c;如服务的独立性、弹性、可伸缩性等。然而&#xff0c;它也带来了一些挑战&#xff0c;特别是在安全性方面。这时候就体…

YOLOv5改进策略:Focaler-IoU损失函数改进

文章目录 1、前言2、摘要3、Focaler-IoU&#xff1a;4、代码实现5、目标检测系列文章 1、前言 ​ 目标检测是计算机视觉的基本任务之一&#xff0c;旨在识别图像中的目标并定位其位置。目标检测算法可分为基于锚点和无锚点的方法。基于锚点的方法包括Faster R-CNN、YOLO系列、…

数据结构 —— 栈 与 队列

1.栈 1.1栈的结构和概念 栈&#xff08;Stack&#xff09;是一种特殊的线性数据结构&#xff0c;它遵循后进先出&#xff08;LIFO&#xff0c;Last In First Out&#xff09;的原则。栈只允许在一端插入和删除数据&#xff0c;这一端被称为栈顶&#xff08;top&#xff09;&a…

Hudi 多表摄取工具 HoodieMultiTableStreamer 配置方法与示例

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

基于SpringBoot和Mybatis实现的留言板案例

目录 一、需求及界面展示 二、准备工作 引入依赖 .yml文件相关配置 数据库数据准备 三、编写后端代码 需求分析 代码结构 Model Mapper Service Controller 前端代码 四、测试 一、需求及界面展示 需求&#xff1a; 1. 输入留言信息&#xff0c;点击提交&…

2024-6-遥远的救世主

2024-6-遥远的救世主 2024-4-18 豆豆 fatux&#xff1a; 2021.5.26 看完电视剧《天道》之后购买本书&#xff0c;断断续续一直没有读完。 非常好奇&#xff0c;一个什么样的作者能写出如此奇书。老丁&#xff0c;一个智者&#xff0c;智者是多么孤独&#xff0c;因为找不到同…

AtCoder Regular Contest 178 A~D

A.Good Permutation 2&#xff08;贪心&#xff09; 题意&#xff1a; 给你一个正整数 N N N和一个由 M M M个正整数 A ( A 1 , A 2 , … , A M ) A(A_{1},A_{2}, \dots,A_{M}) A(A1​,A2​,…,AM​)组成的序列。 在这里&#xff0c; A A A的所有元素都是介于 1 1 1和 N N …

nss做题

[NCTF 2018]签到题 1.f12在index.php中找到flag [NSSCTF 2022 Spring Recruit]ezgame 1.在js源码中就有flag [UUCTF 2022 新生赛]websign 1.打开环境后发现ctrlu和右键&#xff0c;f12都被禁用了。两种方法&#xff0c;第一种&#xff1a;禁用js&#xff1b;第二中提前打开…

数据结构(五)树与二叉树

2024年5月26日一稿(王道P142) 基本概念 术语 性质 二叉树 5.2.2 二叉树存储结构