在sentinel源码中是不支持规则持久化的,一旦sentinel服务宕机,匹配的所有规则将彻底消失。在上篇博客中展示了sentinel的源码流程图,在sentinel dashboard新增一条流控规则(或者其他规则),通过http协议将规则信息发送到客户端,客户端通过socket接收到规则信息后,将信息交给流控规则管理器(AuthorityRuleManager)处理,它会出发流控规则监听器执行更新缓存中的流控规则信息(map缓存)。
故我们需要对其进行改造,改造的方案有两种:
在原始模式中对客户端在缓存更新时,同时将规则保存到本地文件进行持久化。
创建推模式改造工程,使用SPI机制将加载改造类FileDataSoutceInit。
FileDataSoutceInit:
public class FileDataSourceInit implements InitFunc {
@Override
public void init() throws Exception {
// A fake path.
String flowRuleDir = System.getProperty("user.home") + File.separator + "sentinel" + File.separator + "rules";
String flowRuleFile = "flowRule.json";
String flowRulePath = flowRuleDir + File.separator + flowRuleFile;
ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>(
flowRulePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
);
// Register to flow rule manager.
FlowRuleManager.register2Property(ds.getProperty());
WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson);
// Register to writable data source registry so that rules can be updated to file
// when there are rules pushed from the Sentinel Dashboard.
WritableDataSourceRegistry.registerFlowDataSource(wds);
}
private <T> String encodeJson(T t) {
return JSON.toJSONString(t);
}
}
FileRefreshableDataSource:每次更新规则时自动读取持久化文件更新到map缓存。
FileWritableDataSource:写数据源,将sentinel控制台发送过来的规则信息写到持久化文件中。在客户端的socket接收到规则信息后,更新缓存的时候也会将规则信息写入文件中持久化。
推模式是通过注册中心实现的,sentinel控制台——>配置中心——>Sentinel数据源——>sentinel
用户不仅可以通过sentinel控制台进行更新,也可以通过nacos配置中心进行更新,所以在sentinel控制台或nacos中修改规则后,都需要通知对方刷新最新的配置。
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.4.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
<version>1.4.2</version>
<scope>compile</scope>
</dependency>
@Component("flowRuleNacosProvider")
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<String, List<FlowRuleEntity>> converter;
@Override
public List<FlowRuleEntity> getRules(String appName) throws Exception {
String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
NacosConfigUtil.GROUP_ID, 3000);
if (StringUtil.isEmpty(rules)) {
return new ArrayList<>();
}
return converter.convert(rules);
}
}
发布nacos监听事件的写数据源,将规则信息写入nacos配置中心
@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<List<FlowRuleEntity>, String> converter;
@Override
public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
AssertUtil.notEmpty(app, "app name cannot be empty");
if (rules == null) {
return;
}
configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
NacosConfigUtil.GROUP_ID, converter.convert(rules));
}
}
改造完成后,重新打包dashboard:
如此便能将规则持久化到nacos,而且无论是更新nacos配置中心的规则还是sentinel控制台的规则,都会持久化并且通过nacos推送到微服务客户端。
在sentinel中创建限流规则配置,内容如下:
在sentinel-test-client的配置文件中新增配置
spring.cloud.sentinel.datasource.flow-rules.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.flow-rules.nacos.data-id=${spring.application.name}-flow-rules
spring.cloud.sentinel.datasource.flow-rules.nacos.group-id=SENTINEL_GROUP
spring.cloud.sentinel.datasource.flow-rules.nacos.data-type=json
spring.cloud.sentinel.datasource.flow-rules.nacos.rule-type=flow
之后nacos中会自动生成入如下配置
连续访问即出现限流
并且重启sentinel控制台后,已经配置过的流控规则不会丢失。