阅读文本大概需要3分钟。
前一篇【使用Nacos存储Sentinel的限流规则】讲了基于Nacos的Push模式持久化,这里讲下基于本地文件的Pull模式持久化。在网上看到一篇讲这个讲得不错的:
从官网的说明
https://github.com/alibaba/Sentinel/wiki/在生产环境中使用-Sentinel#Pull模式
有如下一张图,总觉得例子欠缺些什么??
琢磨一下,发现原来无论官方的例子,还是网友的例子都没有结合Sentinel讲解规则的Pull。现在开始操作,按照官方的步骤开始操作:
https://github.com/alibaba/Sentinel/wiki/动态规则扩展
在微服务的pom.xml文件引入
com.alibaba.csp
sentinel-datasource-extension
x.y.z
不知道哪里出了问题,到最后也没有搞通?而且还有如下疑问
- 微服务到底连接哪个Sentinel服务?如果没有配置,可能可以连接默认的Sentinel服务
- 如果Sentinel服务的ip和port变了呢?如何配置?也没有找到具体说明?
带着这两个疑问开始学习之旅。因为基于springboot和springcloud讲解,所有Spring Cloud Alibaba这么好的技术,为什么不用呢?
0x01:新建项目olive-pull-sentinel-datasource
- pom.xml文件引入
4.0.0
com.sentinel
olive-pull-sentinel-datasource
0.0.1-SNAPSHOT
jar
org.springframework.boot
spring-boot-starter-parent
2.1.3.RELEASE
olive-pull-sentinel-datasource
http://maven.apache.org
UTF-8
1.8
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
2.2.1.RELEASE
com.alibaba.csp
sentinel-parameter-flow-control
1.7.1
com.alibaba
fastjson
1.2.68
- 编写如下代码
常量类,主要是定义规则文件的目录和名字
package com.sentinel.olive.file;
import java.util.HashMap;
import java.util.Map;
public class PersistenceRuleConstant {
/**
* 存储文件路径
*/
public static final String storePath = System.getProperty("user.home")+"sentinelrules";
/**
* 各种存储sentinel规则映射map
*/
public static final Map rulesMap = new HashMap();
//流控规则文件
public static final String FLOW_RULE_PATH = "flowRulePath";
//降级规则文件
public static final String DEGRAGE_RULE_PATH = "degradeRulePath";
//授权规则文件
public static final String AUTH_RULE_PATH = "authRulePath";
//系统规则文件
public static final String SYSTEM_RULE_PATH = "systemRulePath";
//热点参数文件
public static final String HOT_PARAM_RULE = "hotParamRulePath";
static {
rulesMap.put(FLOW_RULE_PATH,storePath+"flowRule.json");
rulesMap.put(DEGRAGE_RULE_PATH,storePath+"degradeRule.json");
rulesMap.put(SYSTEM_RULE_PATH,storePath+"systemRule.json");
rulesMap.put(AUTH_RULE_PATH,storePath+"authRule.json");
rulesMap.put(HOT_PARAM_RULE,storePath+"hotParamRule.json");
}
}
文件操作类,如果规则文件不存在就创建对应的目录和对应的规则文件
package com.sentinel.olive.file;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RuleFileUtils {
private static final Logger logger = LoggerFactory.getLogger(RuleFileUtils.class);
/**
* 方法实现说明:若路径不存在就创建路径
* @param filePath:文件存储路径
*/
public static void mkdirIfNotExits(String filePath) throws IOException {
File file = new File(filePath);
if(!file.exists()) {
logger.info("创建Sentinel规则目录:{}",filePath);
file.mkdirs();
}
}
/**
* 方法实现说明:若文件不存在就创建路径
* @param ruleFileMap 规则存储文件
*/
public static void createFileIfNotExits(Map ruleFileMap) throws IOException {
Set ruleFilePathSet = ruleFileMap.keySet();
Iterator ruleFilePathIter = ruleFilePathSet.iterator();
while (ruleFilePathIter.hasNext()) {
String ruleFilePathKey = ruleFilePathIter.next();
String ruleFilePath = PersistenceRuleConstant.rulesMap.get(ruleFilePathKey).toString();
File ruleFile = new File(ruleFilePath);
if(ruleFile.exists()) {
logger.info("创建Sentinel 规则文件:{}",ruleFile);
ruleFile.createNewFile();
}
}
}
}
规则的编码和解码操作类
package com.sentinel.olive.file;
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 RuleListParserUtils {
/**
* 流控列表解析器
*/
public static final Converter> flowRuleListParser = new Converter>() {
@Override
public List convert(String source) {
return JSON.parseObject(source, new TypeReference>() {
});
}
};
/**
* 流控列表 编码器
*/
public static final Converter, String> flowRuleEnCoding = new Converter, String>() {
@Override
public String convert(List source) {
return JSON.toJSONString(source);
}
};
public static final Converter> degradeRuleListParser = source -> JSON.parseObject(source,
new TypeReference>() {
});
public static final Converter, String> degradeRuleEnCoding = new Converter, String>() {
@Override
public String convert(List source) {
return JSON.toJSONString(source);
}
};
public static final Converter> systemRuleListParser = source -> JSON.parseObject(source,
new TypeReference>() {
});
public static final Converter, String> systemRuleEnCoding = new Converter, String>() {
@Override
public String convert(List source) {
return JSON.toJSONString(source);
}
};
public static final Converter> authorityRuleListParser = source -> JSON
.parseObject(source, new TypeReference>() {
});
public static final Converter, String> authorityRuleEnCoding = new Converter, String>() {
@Override
public String convert(List source) {
return JSON.toJSONString(source);
}
};
public static final Converter> paramFlowRuleListParser = source -> JSON
.parseObject(source, new TypeReference>() {
});
// public static final Converter, String> paramFlowRuleEnCoding = new Converter, String>() {
// @Override
// public String convert(List source) {
// return JSON.toJSONString(source);
// }
// };
public static final Converter, String> paramFlowRuleEnCoding = source -> encodeJson(source);
private static String encodeJson(T t) {
return JSON.toJSONString(t);
}
}
具体pull模式操作类
package com.sentinel.olive.file;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;
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;
public class PullModeLocalFileDataSource implements InitFunc {
private static final Logger logger = LoggerFactory.getLogger(PullModeLocalFileDataSource.class);
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
@Override
public void init() throws Exception {
logger.info("time:{}读取配置", sdf.format(new Date()));
try {
// 创建文件存储目录(若路径不存在就创建路径)
RuleFileUtils.mkdirIfNotExits(PersistenceRuleConstant.storePath);
// 创建规则文件()
RuleFileUtils.createFileIfNotExits(PersistenceRuleConstant.rulesMap);
// 处理流控规则逻辑
dealFlowRules();
// 处理降级规则
dealDegradeRules();
// 处理系统规则
dealSystemRules();
// 热点参数规则
dealParamFlowRules();
// 授权规则
dealAuthRules();
} catch (Exception e) {
logger.error("错误原因:{}", e);
}
}
/**
* 方法实现说明:处理流控规则逻辑
*/
private void dealFlowRules() throws FileNotFoundException {
String ruleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.FLOW_RULE_PATH).toString();
// 创建流控规则的可读数据源
ReadableDataSource> flowRuleRDS = new FileRefreshableDataSource(ruleFilePath,
RuleListParserUtils.flowRuleListParser);
// 将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
FlowRuleManager.register2Property(flowRuleRDS.getProperty());
WritableDataSource> flowRuleWDS = new FileWritableDataSource>(ruleFilePath,
RuleListParserUtils.flowRuleEnCoding);
// 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
// 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
}
// 处理降级规则
private void dealDegradeRules() throws FileNotFoundException {
String degradeRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.DEGRAGE_RULE_PATH).toString();
// 降级规则
ReadableDataSource> degradeRuleRDS = new FileRefreshableDataSource(degradeRulePath,
RuleListParserUtils.degradeRuleListParser);
DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());
WritableDataSource> degradeRuleWDS = new FileWritableDataSource(degradeRulePath,
RuleListParserUtils.degradeRuleEnCoding);
WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);
}
// 处理系统规则
private void dealSystemRules() throws FileNotFoundException {
String systemRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.SYSTEM_RULE_PATH).toString();
// 系统规则
ReadableDataSource> systemRuleRDS = new FileRefreshableDataSource(systemRulePath,
RuleListParserUtils.systemRuleListParser);
SystemRuleManager.register2Property(systemRuleRDS.getProperty());
WritableDataSource> systemRuleWDS = new FileWritableDataSource(systemRulePath,
RuleListParserUtils.systemRuleEnCoding);
WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
}
// 热点参数规则
private void dealParamFlowRules() throws FileNotFoundException {
String paramFlowRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.HOT_PARAM_RULE).toString();
// 热点参数规则
ReadableDataSource> paramFlowRuleRDS = new FileRefreshableDataSource(
paramFlowRulePath, RuleListParserUtils.paramFlowRuleListParser);
ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());
WritableDataSource> paramFlowRuleWDS = new FileWritableDataSource(paramFlowRulePath,
RuleListParserUtils.paramFlowRuleEnCoding);
ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
}
private void dealAuthRules() throws FileNotFoundException {
String authFlowRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.AUTH_RULE_PATH).toString();
// 授权规则
ReadableDataSource> authorityRuleRDS = new FileRefreshableDataSource(authFlowRulePath,
RuleListParserUtils.authorityRuleListParser);
AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());
WritableDataSource> authorityRuleWDS = new FileWritableDataSource(authFlowRulePath,
RuleListParserUtils.authorityRuleEnCoding);
WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);
}
}
编写了以上代码就可以,通过SPI扩展机制进行扩展,在微服务工程 olive-pull-sentinel-datasource的resources目录下创建META-INF/services目录,并新建文件名为com.alibaba.csp.sentinel.init.InitFunc文件。内容是PullModeLocalFileDataSource类全路径类名
0x02:配置文件application.yml
看到这张图总有解决了以上的疑问了,提供了配置项,配置Sentinel服务对应的ip和端口
0x03:创建测试控制器和springboot启动类
测试控制器
package com.sentinel.olive.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/getUser")
public Map getUser() {
Map result = new HashMap();
result.put("code", "000000");
result.put("message", "ok");
return result;
}
}
springboot启动类
package com.sentinel.olive;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
0x04:启动并测试验证
启动服务
- sentinel-dashboard服务
- olive-pull-sentinel-datasource微服务
验证
- sentinel-dashboard创建规则,olive-pull-sentinel-datasource微服务检测到sentinel-dashboard变化
- 修改json规则文件的规则,sentinel-dashboard检测到json规则编码
访问微服务的http://localhost:8866/getUser接口
访问sentinel-dashboard服务:http://127.0.0.1:8080/
创建流控规则
olive-pull-sentinel-datasource检测到流控规则的变化并产生flowRule.json文件
修改流控规则文件json
sentinel-dashboard查看规则的变化
关注我
每天进步一点点
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
大家好,我是wangmy。 众所周知动态规划将原问题分解成若干个子问题,再把子问题分解成若干更多子问题。先求解子问题,再从这些子问题的解得到原问题的解。 今天我给大家分享一下动态规划的几道题和参考代码。 数字三角形 题目描述(Description) 编辑 输…