在改造Sentinel sashboard实现和数据源持久化的过程中,遇到了热点规则及授权规则和单机模式无法兼容的问题,就是你改变了集群的热点规则及授权规则后,虽然持久化到数据源中,但是单机模式无法解析规则。使得规则无法打通。
究其原因,就是集群V2模式保存的数据,多了一级rule。所以保存和读取的时候就要稍微调整一下。
单机的loadConfig解析
[{"burstCount":0,"clusterConfig":{"fallbackToLocalWhenFail":true,"sampleCount":10,"thresholdType":0,"windowIntervalMs":1000},"clusterMode":false,"controlBehavior":0,"count":8888.0,"durationInSec":8888,"grade":1,"limitApp":"default","maxQueueingTimeMs":0,"paramFlowItemList":[],"paramIdx":8888,"resource":"66666"}]
V2的loadConfig解析
[{"app":"i5xforyou","gmtCreate":1594287624052,"gmtModified":1594289440542,"id":38,"ip":"192.168.14.187","port":8720,"rule":{"burstCount":0,"clusterConfig":{"fallbackToLocalWhenFail":true,"sampleCount":10,"thresholdType":0,"windowIntervalMs":1000},"clusterMode":false,"controlBehavior":0,"count":111.0,"durationInSec":1111112,"grade":1,"limitApp":"default","maxQueueingTimeMs":0,"paramFlowItemList":[],"paramIdx":22222222,"resource":"SSSS"}}]
原理不过多在解释了,解决方法如下,
以Publisher方法为例,增加如下方法
private String parseRules(String rules) {
JSONArray oldRuleJsons = JSONArray.parseArray(rules);
for (int i = 0; i < oldRuleJsons.size(); i++) {
JSONObject oldRuleJson = oldRuleJsons.getJSONObject(i);
JSONObject ruleJson = oldRuleJson.getJSONObject("rule");
oldRuleJson.putAll(ruleJson);
oldRuleJson.remove("rule");
}
return oldRuleJsons.toJSONString();
}
byte[] data = CollectionUtils.isEmpty(rules) ? "[]".getBytes() : converter.convert(rules).getBytes();
变为
byte[] data = CollectionUtils.isEmpty(rules) ? "[]".getBytes() : this.parseRules(converter.convert(rules)).getBytes();
provider方法则有些不同
授权规则需要添加如下方法:
private String parseRules(String rules) {
JSONArray newRuleJsons = new JSONArray();
JSONArray ruleJsons = JSONArray.parseArray(rules);
for (int i = 0; i < ruleJsons.size(); i++) {
JSONObject ruleJson = ruleJsons.getJSONObject(i);
AuthorityRuleEntity ruleEntity = JSON.parseObject(ruleJson.toJSONString(), AuthorityRuleEntity.class);
JSONObject newRuleJson = JSON.parseObject(JSON.toJSONString(ruleEntity));
AuthorityRule rule = JSON.parseObject(ruleJson.toJSONString(), AuthorityRule.class);
newRuleJson.put("rule", rule);
newRuleJsons.add(newRuleJson);
}
return newRuleJsons.toJSONString();
}
热点规则需要添加如下方法:
private String parseRules(String rules) {
JSONArray newRuleJsons = new JSONArray();
JSONArray ruleJsons = JSONArray.parseArray(rules);
for (int i = 0; i < ruleJsons.size(); i++) {
JSONObject ruleJson = ruleJsons.getJSONObject(i);
ParamFlowRuleEntity ruleEntity = JSON.parseObject(ruleJson.toJSONString(), ParamFlowRuleEntity.class);
JSONObject newRuleJson = JSON.parseObject(JSON.toJSONString(ruleEntity));
ParamFlowRule rule = JSON.parseObject(ruleJson.toJSONString(), ParamFlowRule.class);
newRuleJson.put("rule", rule);
newRuleJsons.add(newRuleJson);
}
return newRuleJsons.toJSONString();
}
getRules方法下的
return converter.convert(s); 调整为 return converter.convert(this.parseRules(s));
问题解决。
更多关于 sentinel dashboard 持久化改造 zookeeper nacos的源码,https://gitee.com/ankeway/Sentinel.git master-dashboard分支查看