由於使用到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>: 推送規則
