在之前的练习中,只要应用重启,就需要重新配置,这样在我们实际的项目是非常不实用的,那么有没有办法把我们配置的规则保存下来呢?答案是YES,那么接下来,给大家来介绍如何将Sentinel规则持久化。
Document: 传送门
- File Datasource(文件存储)
- Pull 模式
- Push 模式
- Nacos configuration
- Apollo
File Datasource
Pull 模式
原理:
扩展写数据源(WritableDataSource
), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等
pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的WritableDataSourceRegistry
中。
Pull Demo
Step 1: 添加配置
com.alibaba.csp sentinel-datasource-extension 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 Isaac.Zhang | 若初 * @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
> flowRuleRDS = new FileRefreshableDataSource<>( flowRulePath, flowRuleListParser ); // 将可读数据源注册至FlowRuleManager // 这样当规则文件发生变化时,就会更新规则到内存 FlowRuleManager.register2Property(flowRuleRDS.getProperty()); WritableDataSource - > flowRuleWDS = new FileWritableDataSource<>(
flowRulePath,
this::encodeJson
);
// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
// 降级规则
ReadableDataSource
> degradeRuleRDS = new FileRefreshableDataSource<>( degradeRulePath, degradeRuleListParser ); DegradeRuleManager.register2Property(degradeRuleRDS.getProperty()); WritableDataSource - > degradeRuleWDS = new FileWritableDataSource<>(
degradeRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);
// 系统规则
ReadableDataSource
> systemRuleRDS = new FileRefreshableDataSource<>( systemRulePath, systemRuleListParser ); SystemRuleManager.register2Property(systemRuleRDS.getProperty()); WritableDataSource - > systemRuleWDS = new FileWritableDataSource<>(
systemRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
// 授权规则
ReadableDataSource
> authorityRuleRDS = new FileRefreshableDataSource<>( flowRulePath, authorityRuleListParser ); AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty()); WritableDataSource - > authorityRuleWDS = new FileWritableDataSource<>(
authorityRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);
// 热点参数规则
ReadableDataSource
> hotParamFlowRuleRDS = new FileRefreshableDataSource<>( hotParamFlowRulePath, hotParamFlowRuleListParser ); ParamFlowRuleManager.register2Property(hotParamFlowRuleRDS.getProperty()); WritableDataSource - > paramFlowRuleWDS = new FileWritableDataSource<>(
hotParamFlowRulePath,
this::encodeJson
);
ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
}
/**
* 流控规则对象转换
*/
private Converter
> flowRuleListParser = source -> JSON.parseObject( source, new TypeReference - >() {
}
);
/**
* 降级规则对象转换
*/
private Converter
> degradeRuleListParser = source -> JSON.parseObject( source, new TypeReference - >() {
}
);
/**
* 系统规则对象转换
*/
private Converter
> systemRuleListParser = source -> JSON.parseObject( source, new TypeReference - >() {
}
);
/**
* 授权规则对象转换
*/
private Converter
> authorityRuleListParser = source -> JSON.parseObject( source, new TypeReference - >() {
}
);
/**
* 热点规则对象转换
*/
private Converter
> hotParamFlowRuleListParser = source -> JSON.parseObject( source, new TypeReference - >() {
}
);
/**
* 创建目录
*
* @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
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 WIKI
Push 模式
推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现
ReadableDataSource
接口端监听规则中心实时获取变更,流程如下:
实现原理
- 控制台推送规则到Nacos/远程配置中心
- Sentinel client 舰艇Nacos配置变化,更新本地缓存
shared_center service 加工
- 添加依赖
com.alibaba.csp sentinel-datasource-nacos - 添加配置
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文件com.alibaba.csp sentinel-datasource-nacos 偷懒模式:复制
sentinel-dashboard
项目下test下的nacos包(src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos
到src/main/java/com/alibaba/csp/sentinel/dashboard/rule
下修改controller中的默认provider & publisher
com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2
中@Autowired // @Qualifier("flowRuleDefaultProvider") @Qualifier("flowRuleNacosProvider") private DynamicRuleProvider
- > ruleProvider;
@Autowired
// @Qualifier("flowRuleDefaultPublisher")
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher
- > rulePublisher;
打开
/Sentinel-1.6.2/sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html
文件,修改代码:--- 改为
- NACOS 流控规则 V1
Dashboard中要修改的代码已经好了。
重新启动 Sentinel-dashboard
mvn clean package -DskipTests
测试效果
Sentinel 添加流控规则:
Nacos 查看同步的配置: