[Spring-Cloud-Alibaba] Sentinel 规则持久化
在之前的练习中,只要应用重启,就需要重新配置,这样在我们实际的项目是非常不实用的,那么有没有办法把我们配置的规则保存下来呢?答案是YES,那么接下来,给大家来介绍如何将Sentinel规则持久化。
Document: 传送门
File Datasource(文件存储)Pull 模式Push 模式Nacos configurationApolloFile DatasourcePull 模式原理:
扩展写数据源(WritableDataSource
), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等
pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的WritableDataSourceRegistry
中。
过程如下:
Pull DemoStep 1: 添加配置
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-extension</artifactId> </dependency>
Step 2: 编写持久化代码,实现com.alibaba.csp.sentinel.init.InitFunc
import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;import com.alibaba.csp.sentinel.datasource.*;import com.alibaba.csp.sentinel.init.InitFunc;import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;import com.alibaba.csp.sentinel.slots.system.SystemRule;import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.TypeReference;import java.io.File;import java.io.IOException;import java.util.List;/*** FileDataSourceInit for : 自定义Sentinel存储文件数据源加载类** @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>* @since 2019/7/21*/public class FileDataSourceInit implements InitFunc { @Override public void init() throws Exception { // TIPS: 如果你对这个路径不喜欢,可修改为你喜欢的路径 String ruleDir = System.getProperty("user.home") + "/sentinel/rules"; String flowRulePath = ruleDir + "/flow-rule.json"; String degradeRulePath = ruleDir + "/degrade-rule.json"; String systemRulePath = ruleDir + "/system-rule.json"; String authorityRulePath = ruleDir + "/authority-rule.json"; String hotParamFlowRulePath = ruleDir + "/param-flow-rule.json"; this.mkdirIfNotExits(ruleDir); this.createFileIfNotExits(flowRulePath); this.createFileIfNotExits(degradeRulePath); this.createFileIfNotExits(systemRulePath); this.createFileIfNotExits(authorityRulePath); this.createFileIfNotExits(hotParamFlowRulePath); // 流控规则 ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>( flowRulePath, flowRuleListParser ); // 将可读数据源注册至FlowRuleManager // 这样当规则文件发生变化时,就会更新规则到内存 FlowRuleManager.register2Property(flowRuleRDS.getProperty()); WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>( flowRulePath, this::encodeJson ); // 将可写数据源注册至transport模块的WritableDataSourceRegistry中 // 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中 WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS); // 降级规则 ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>( degradeRulePath, degradeRuleListParser ); DegradeRuleManager.register2Property(degradeRuleRDS.getProperty()); WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>( degradeRulePath, this::encodeJson ); WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS); // 系统规则 ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>( systemRulePath, systemRuleListParser ); SystemRuleManager.register2Property(systemRuleRDS.getProperty()); WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>( systemRulePath, this::encodeJson ); WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS); // 授权规则 ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new FileRefreshableDataSource<>( flowRulePath, authorityRuleListParser ); AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty()); WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>( authorityRulePath, this::encodeJson ); WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS); // 热点参数规则 ReadableDataSource<String, List<ParamFlowRule>> hotParamFlowRuleRDS = new FileRefreshableDataSource<>( hotParamFlowRulePath, hotParamFlowRuleListParser ); ParamFlowRuleManager.register2Property(hotParamFlowRuleRDS.getProperty()); WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>( hotParamFlowRulePath, this::encodeJson ); ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS); } /** * 流控规则对象转换 */ private Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<FlowRule>>() { } ); /** * 降级规则对象转换 */ private Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<DegradeRule>>() { } ); /** * 系统规则对象转换 */ private Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<SystemRule>>() { } ); /** * 授权规则对象转换 */ private Converter<String, List<AuthorityRule>> authorityRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<AuthorityRule>>() { } ); /** * 热点规则对象转换 */ private Converter<String, List<ParamFlowRule>> hotParamFlowRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<ParamFlowRule>>() { } ); /** * 创建目录 * * @param filePath */ private void mkdirIfNotExits(String filePath) { File file = new File(filePath); if (!file.exists()) { file.mkdirs(); } } /** * 创建文件 * * @param filePath * @throws IOException */ private void createFileIfNotExits(String filePath) throws IOException { File file = new File(filePath); if (!file.exists()) { file.createNewFile(); } } private <T> String encodeJson(T t) { return JSON.toJSONString(t); }}
Step 3: 启用上述代码
resource 目录下创建 resources/META-INF/services
目录并创建文件com.alibaba.csp.sentinel.init.InitFunc
,内容为:
com.sxzhongf.sharedcenter.configuration.sentinel.datasource.FileDataSourceInit
Pull 优缺点优点简单,无任何依赖没有额外依赖缺点不保证一致性(规则是使用FileRefreshableDataSource
定时更新,会有延迟)实时性不保证(规则是使用FileRefreshableDataSource
定时更新)拉取过于频繁也可能会有性能问题由于文件存储于本地,容易丢失参考资料:ITMUCH Sentinel WIKIPush 模式
推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现
ReadableDataSource
接口端监听规则中心实时获取变更,流程如下:
<img src="https://user-images.githubusercontent.com/9434884/45406233-645e8380-b698-11e8-8199-0c917403238f.png" width="500" />
实现原理
控制台推送规则到Nacos/远程配置中心Sentinel client 舰艇Nacos配置变化,更新本地缓存shared_center service 加工
添加依赖 <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
添加配置
spring: cloud: sentinel: datasource: sxzhongf_flow: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-flow-rules groupId: SENTINEL_GROUP # 规则类型,取值见:org.springframework.cloud.alibaba.sentinel.datasource.RuleType rule_type: flow sxzhongf_degrade: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-degrade-rules groupId: SENTINEL_GROUP rule-type: degrade
Sentinel dashboard 加工
Dashboard 规则改造主要通过2个接口:
com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider
& com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher
Download Sentinel Source Code
修改原sentinel-dashboard
项目下的POM文件 <!-- for Nacos rule publisher sample --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <!--注释掉原文件中的scope,让其不仅在test的时候生效--> <!--<scope>test</scope>--> </dependency>
偷懒模式:复制sentinel-dashboard
项目下test下的nacos包(
src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos
到 src/main/java/com/alibaba/csp/sentinel/dashboard/rule
下
com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2
中
@Autowired // @Qualifier("flowRuleDefaultProvider") @Qualifier("flowRuleNacosProvider") private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider; @Autowired // @Qualifier("flowRuleDefaultPublisher") @Qualifier("flowRuleNacosPublisher") private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
打开 /Sentinel-1.6.2/sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html
文件,修改代码:
<!--<li ui-sref-active="active">--> <!--<a ui-sref="dashboard.flow({app: entry.app})">--> <!--<i class="glyphicon glyphicon-filter"></i> 流控规则 V1</a>--><!--</li>-->---改为 <li ui-sref-active="active"> <a ui-sref="dashboard.flow({app: entry.app})"> <i class="glyphicon glyphicon-filter"></i> NACOS 流控规则 V1</a> </li>
Dashboard中要修改的代码已经好了。
重新启动 Sentinel-dashboard mvn clean package -DskipTests
测试效果
Sentinel 添加流控规则:
Nacos 查看同步的配置:
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。