在客户端改造持久化方案,需要通过SPI模式实现。具体思路就是接收到Sentinel推送的规则后,将规则保存到本地。
第一步
新增一个实现类。如【PullModeByFileDataSource】。
package com.example.demo.sentinelSpi;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
import com.alibaba.csp.sentinel.datasource.FileWritableDataSource;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
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;
/**
* Sentinel 拉模式持久化方案
*
* @author AdminMall
*
*/
public class PullModeByFileDataSource implements InitFunc {
/**
* 初始化方法
*/
@Override
public void init() throws Exception {
System.out.println("-------开始创建Sentinel规则目录");
// 先创建保存Sentinel规则的目录
String saveDirct = "G:/sentinel/rules";
File fileDirct = new File(saveDirct);
if (!fileDirct.isDirectory()) {
fileDirct.mkdirs();
}
// 创建规则文件
Map<String, String> fileMap = new HashMap<>();
fileMap.put("flowRule", saveDirct + "/flowRule.json");// 流控规则文件
fileMap.put("degradeRule", saveDirct + "/degradeRule.json");// 降级规则文件
fileMap.put("systemRule", saveDirct + "/systemRule.json");// 系统规则文件
fileMap.put("authRule", saveDirct + "/authRule.json");// 授权规则文件
fileMap.put("hotRule", saveDirct + "/hotRule.json");// 热点规则文件
for (String key : fileMap.keySet()) {
File file = new File(fileMap.get(key));
if (!file.exists()) {
file.createNewFile();
}
}
// 流控规则持久化
flowRule(saveDirct + "/flowRule.json");
// 降级规则持久化
degradeRule(saveDirct + "/degradeRule.json");
// 系统规则持久化
systemRule(saveDirct + "/systemRule.json");
// 授权规则持久化
authRule(saveDirct + "/authRule.json");
// 热点规则持久化
hotRule(saveDirct + "/hotRule.json");
}
/**
* 流控规则启用
*
* @param flowRulePath
* @throws FileNotFoundException
*/
public void flowRule(String flowRulePath) throws FileNotFoundException {
// 流控规则
ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(flowRulePath,
SentinelConverTool.flowRuleListParser);
// 可以指定刷新时间,比如20秒,默认是3秒钟
//参数说明;文件,轮询秒数,文件大小,字符集
// ReadableDataSource<String, List<FlowRule>> flowRuleRDS2 = new
// FileRefreshableDataSource<>(new
// File(flowRulePath),SentinelConverTool.flowRuleListParser, 20000L, (1024 *
// 1024), Charset.forName("utf-8"));
// 将可读数据源注册至FlowRuleManager
// 这样当规则文件发生变化时,就会更新规则到内存
FlowRuleManager.register2Property(flowRuleRDS.getProperty());
// 写数据源
WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(flowRulePath,
SentinelConverTool.flowRuleStringParser);
// 第二种写法
// WritableDataSource<List<FlowRule>> flowRuleWDS = new
// FileWritableDataSource<>(flowRulePath,this::encodeJson;
// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
}
/**
* 降级规则启用
*
* @param degradeRulePath
* @throws FileNotFoundException
*/
public void degradeRule(String degradeRulePath) throws FileNotFoundException {
// 降级规则
ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>(degradeRulePath,
SentinelConverTool.degradeRuleListParser);
// 将可读数据源注册至DegradeRuleManager
// 这样当规则文件发生变化时,就会更新规则到内存
DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());
// 写数据源
WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>(degradeRulePath,
this::encodeJson);
// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);
}
/**
* 系统规则启用
*
* @param systemRulePath
* @throws FileNotFoundException
*/
public void systemRule(String systemRulePath) throws FileNotFoundException {
// 系统规则
ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>(systemRulePath,
SentinelConverTool.systemRuleListParser);
// 将可读数据源注册至SystemRuleManager
// 这样当规则文件发生变化时,就会更新规则到内存
SystemRuleManager.register2Property(systemRuleRDS.getProperty());
// 写数据源
WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(systemRulePath,
this::encodeJson);
// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
}
/**
* 授权规则启用
*
* @param authRulePath
* @throws FileNotFoundException
*/
public void authRule(String authRulePath) throws FileNotFoundException {
// 授权规则
ReadableDataSource<String, List<AuthorityRule>> authRuleRDS = new FileRefreshableDataSource<>(authRulePath,
SentinelConverTool.authRuleListParser);
// 将可读数据源注册至AuthorityRuleManager
// 这样当规则文件发生变化时,就会更新规则到内存
AuthorityRuleManager.register2Property(authRuleRDS.getProperty());
// 写数据源
WritableDataSource<List<AuthorityRule>> authRuleWDS = new FileWritableDataSource<>(authRulePath,
this::encodeJson);
// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
WritableDataSourceRegistry.registerAuthorityDataSource(authRuleWDS);
}
/**
* 热点规则启用
*
* @param hotRulePath
* @throws FileNotFoundException
*/
public void hotRule(String hotRulePath) throws FileNotFoundException {
// 系统规则
ReadableDataSource<String, List<ParamFlowRule>> hotRuleRDS = new FileRefreshableDataSource<>(hotRulePath,
SentinelConverTool.hotRuleListParser);
// 将可读数据源注册至ParamFlowRuleManager
// 这样当规则文件发生变化时,就会更新规则到内存
ParamFlowRuleManager.register2Property(hotRuleRDS.getProperty());
// 写数据源
WritableDataSource<List<ParamFlowRule>> hotRuleWDS = new FileWritableDataSource<>(hotRulePath,
this::encodeJson);
// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
ModifyParamFlowRulesCommandHandler.setWritableDataSource(hotRuleWDS);
}
private <T> String encodeJson(T t) {
return JSON.toJSONString(t);
}
}
依赖的配置类【SentinelConverTool】
package com.example.demo.sentinelSpi;
import java.util.List;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
public class SentinelConverTool {
// 流控转换
public static Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject(source,
new TypeReference<List<FlowRule>>() {
});
// 降级转换
public static Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(source,
new TypeReference<List<DegradeRule>>() {
});
// 系统转换
public static Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(source,
new TypeReference<List<SystemRule>>() {
});
// 授权转换
public static Converter<String, List<AuthorityRule>> authRuleListParser = source -> JSON.parseObject(source,
new TypeReference<List<AuthorityRule>>() {
});
// 热点
public static Converter<String, List<ParamFlowRule>> hotRuleListParser = source -> JSON.parseObject(source,
new TypeReference<List<ParamFlowRule>>() {
});
// 转码
public static Converter<List<FlowRule>, String> flowRuleStringParser = new Converter<List<FlowRule>, String>() {
@Override
public String convert(List<FlowRule> source) {
return JSON.toJSONString(source);
}
};
}
第二步
在【resource】目录下创建【META-INF/services】目录。如图
第三步
在services目录下创建【com.alibaba.csp.sentinel.init.InitFunc】文件。文件名称为固定写法。如图。
第四步
编辑文件内容。将自定义的【PullModeByFileDataSource】类全路径,写到文件中。
第五步
测试。访问接口后,在【Sentinel】控制台配置相关规则后,客户端会持久化。文件中的内容也会自动填充。