Sentinel Dashboard 规则联动持久化方案

2024-05-26 16:12

本文主要是介绍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";@Overridepublic 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 信息, 最好读取配置信息,这里演示,先写死*/@Beanpublic ConfigService nacosConfigService() throws Exception {return ConfigFactory.createConfigService("127.0.0.1:8848");}
}

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

@Component("flowRuleNacosProvider")
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {@Autowiredprivate ConfigService configService;@Overridepublic 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>> {@Autowiredprivate ConfigService configService;@Overridepublic 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 中了,并且多次访问测试接口,规则也依然生效:

在这里插入图片描述

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

这篇关于Sentinel Dashboard 规则联动持久化方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1004952

相关文章

Java实现本地缓存的常用方案介绍

《Java实现本地缓存的常用方案介绍》本地缓存的代表技术主要有HashMap,GuavaCache,Caffeine和Encahche,这篇文章主要来和大家聊聊java利用这些技术分别实现本地缓存的方... 目录本地缓存实现方式HashMapConcurrentHashMapGuava CacheCaffe

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

利用Python实现可回滚方案的示例代码

《利用Python实现可回滚方案的示例代码》很多项目翻车不是因为不会做,而是走错了方向却没法回头,技术选型失败的风险我们都清楚,但真正能提前规划“回滚方案”的人不多,本文从实际项目出发,教你如何用Py... 目录描述题解答案(核心思路)题解代码分析第一步:抽象缓存接口第二步:实现两个版本第三步:根据 Fea

Nginx路由匹配规则及优先级详解

《Nginx路由匹配规则及优先级详解》Nginx作为一个高性能的Web服务器和反向代理服务器,广泛用于负载均衡、请求转发等场景,在配置Nginx时,路由匹配规则是非常重要的概念,本文将详细介绍Ngin... 目录引言一、 Nginx的路由匹配规则概述二、 Nginx的路由匹配规则类型2.1 精确匹配(=)2

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R

MySQL精准控制Binlog日志数量的三种方案

《MySQL精准控制Binlog日志数量的三种方案》作为数据库管理员,你是否经常为服务器磁盘爆满而抓狂?Binlog就像数据库的“黑匣子”,默默记录着每一次数据变动,但若放任不管,几天内这些日志文件就... 目录 一招修改配置文件:永久生效的控制术1.定位my.cnf文件2.添加核心参数不重启热更新:高手应

MySQL中like模糊查询的优化方案

《MySQL中like模糊查询的优化方案》在MySQL中,like模糊查询是一种常用的查询方式,但在某些情况下可能会导致性能问题,本文将介绍八种优化MySQL中like模糊查询的方法,需要的朋友可以参... 目录1. 避免以通配符开头的查询2. 使用全文索引(Full-text Index)3. 使用前缀索

Python解决雅努斯问题实例方案详解

《Python解决雅努斯问题实例方案详解》:本文主要介绍Python解决雅努斯问题实例方案,雅努斯问题是指AI生成的3D对象在不同视角下出现不一致性的问题,即从不同角度看物体时,物体的形状会出现不... 目录一、雅努斯简介二、雅努斯问题三、示例代码四、解决方案五、完整解决方案一、雅努斯简介雅努斯(Janu

Redis持久化机制之RDB与AOF的使用

《Redis持久化机制之RDB与AOF的使用》:本文主要介绍Redis持久化机制之RDB与AOF的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis持久化机制-RDB与AOF一、RDB持久化机制1、RDB简介2、RDB的工作原理3、RDB的优缺点4

电脑找不到mfc90u.dll文件怎么办? 系统报错mfc90u.dll丢失修复的5种方案

《电脑找不到mfc90u.dll文件怎么办?系统报错mfc90u.dll丢失修复的5种方案》在我们日常使用电脑的过程中,可能会遇到一些软件或系统错误,其中之一就是mfc90u.dll丢失,那么,mf... 在大部分情况下出现我们运行或安装软件,游戏出现提示丢失某些DLL文件或OCX文件的原因可能是原始安装包