sentinel-dashboard改造持久化至nacos

由于使用到sentinel限流,需要对sentinel控制台进行改造,将流控规则持久化到nacos上。然后在网上寻找一些快速入口,发现几乎是千篇一律,都是提供了一个flow的示例。
即在官方源码中提供的test中的com.alibaba.csp.sentinel.dashboard的rule包下,但是如果使用这个规则会发生问题,sentinel计量服务获取不到nacos上的热点和授权规则的值,
经查验发现从dashboard上推送规则存储的时候,resource不在第一级目录,即存储规则的数据结构和客户端的不对等。

由此可以分析,是不是Authority和param-flow在推送的publisher或者去获取规则的provider不适配?针对Converter做一些操作。

我们先来看看flow,degrade,以及system的持久化到nacos上的做法,再来分析一下这个原理.

1.新建一个FlowRuleNacosProvider 来实现 DynamicRuleProvider用来读取存在nacos上的流控规则文件

2.新建一个FlowRuleNacosPublisher 来实现 DynamicRulePublisher 用来发布流控规则至nacos上

3.写一些转换器将规则对象转换成json字符串发布到nacos上,以及将从nacos上读取的json字符串转换成规则对象

4.最后将这些peovider和publish在各自的规则controller中替换掉 SentinelApiClient(操作内存的规则对象)

@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

List<FlowRuleEntity> rules = ruleProvider.getRules(app);

private void publishRules(/*@NonNull*/ String app) throws Exception {
    List<FlowRuleEntity> rules = repository.findAllByApp(app);
    rulePublisher.publish(app, rules);
}

看看param,Authority,以及gateway的持久化到nacos上的做法

1.新建一个FlowRuleNacosProvider 来实现 DynamicRuleProvider用来读取存在nacos上的流控规则文件

2.编写发布规则的转换器

@Bean
public Converter<List<ParamFlowRuleEntity>, String> paramRuleEntityEncoder() {
    return rules -> JSON.toJSONString(
            rules.stream().map(ParamFlowRuleEntity::getRule).collect(Collectors.toList()));
}

param,Authority 和前面三个的不同之处只在于这两处,网关也类似于这个。

分析以及解决方法思路

FlowRuleEntity implements RuleEntity
ParamFlowRuleEntity extends AbstractRuleEntity
从上面两类的继承结构中可以看出,两个规则类的结构是不一样的,来看看AbstractRuleEntity中做了什么

AbstractRuleEntity 中将规则封装进了一个对象属性rule中,导致两种规则的结构不一致,自然发布规则和读取规则的转换也不一致。
那为什么要进行这样的修改呢,其实模仿内存中的做法就行了(原生SentinelApiClient是利用Socket进行推到客户端的),只是规则存放目标地址变更而已。

动态实现数据源原理

正常持久化的两种思路:pull 和 push
①采用pull模式,扩展写数据源(WritableDataSource),即sentinel控制台改变规则后就推到本地文件,客户端主动向这个文件定期轮询拉取规则;
②push模式,扩展读数据源(ReadableDataSource),规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用nacos,zk等配置中心

详见官网注册数据源的两种方式https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95:

①调用以下方法将数据源注册至指定的规则管理器中:
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, parser);
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
②借助 Sentinel 的 InitFunc SPI 扩展接口

采用push模式的话,以nacos为例,需要改写sentinel-dashboard源码,使得在dashboard上更改规则时,能够将规则推送到nacos上

DynamicRuleProvider<T>: 拉取规则
DynamicRulePublisher<T>: 推送规则
posted @ 2021-04-15 15:50  cherishDouble  阅读(1036)  评论(0编辑  收藏  举报