任务
- nacos 的选择器数据同步逻辑
- apache dubbo 的底层原理
nacos 数据同步原理
原理剖析
上次聊到了使用 nacos 进行数据同步时,有可能出现 selectorData 中出现旧的 id(垃圾数据),从而导致网关请求时,无法找到对应 id 的 ruleData,从而报 can not match rule data 的异常。
现在来看看 soul-admin 的数据同步逻辑。从代码中可以得出结论:
- SyncDataService 的 syncPluginData 是通过 pluginId 通知数据发生改变。
- NacosSyncDataService 的 start 会监听数据的变化。重点关注 NacosCacheHandler 的 updateSelectorMap , 这里会根据监听到的 configInfo 来对 selectorData 进行删除和新增。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| // dubbo 插件的 pluginId 是 6 public boolean syncPluginData(final String pluginId) { // 找到 dubbo 插件 PluginVO pluginVO = pluginService.findById(pluginId); // 通知 PLUGIN 数据发生改变 eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.PLUGIN, DataEventTypeEnum.UPDATE, Collections.singletonList(PluginTransfer.INSTANCE.mapDataTOVO(pluginVO)))); // 找到 selectorDataList List<SelectorData> selectorDataList = selectorService.findByPluginId(pluginId); if (CollectionUtils.isNotEmpty(selectorDataList)) { // 通知 SELECTOR 数据发生改变 eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.SELECTOR, DataEventTypeEnum.REFRESH, selectorDataList)); // 找到所有的 ruleDataList List<RuleData> allRuleDataList = new ArrayList<>(); for (SelectorData selectData : selectorDataList) { List<RuleData> ruleDataList = ruleService.findBySelectorId(selectData.getId()); allRuleDataList.addAll(ruleDataList); } // 通知 RULE 数据发生改变 eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.RULE, DataEventTypeEnum.REFRESH, allRuleDataList)); } return true; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public void start() { //PLUGIN watcherData(PLUGIN_DATA_ID, this::updatePluginMap); //SELECTOR watcherData(SELECTOR_DATA_ID, this::updateSelectorMap); //RULE watcherData(RULE_DATA_ID, this::updateRuleMap); //META watcherData(META_DATA_ID, this::updateMetaDataMap); //AUTH watcherData(AUTH_DATA_ID, this::updateAuthMap); }
protected void updateSelectorMap(final String configInfo) { try { //将 json 的数组转化为列表 List<SelectorData> selectorDataList = GsonUtils.getInstance().toObjectMapList(configInfo, SelectorData.class).values().stream().flatMap(Collection::stream).collect(Collectors.toList()); selectorDataList.forEach(selectorData -> Optional.ofNullable(pluginDataSubscriber).ifPresent(subscriber -> { //这里是删除 selector 的数据 subscriber.unSelectorSubscribe(selectorData); //这里是新增 selector 的数据 subscriber.onSelectorSubscribe(selectorData); })); } catch (JsonParseException e) { log.error("sync selector data have error:", e); } }
|
小结
从这里可以看出,数据同步的时候,如果删除数据的动作不是通过 admin 去操作的话,就无法通知到 nacos,则可能存在两条重复的 dubbo plugin 的数据,有一条垃圾数据无法被删除,从而导致请求失败。
思考:这里是不是可以将 selectorData 根据 pluginId 和 name 确定唯一性,避免请求时找到垃圾数据,从而导致请求失败。
Author:
Eazon Shaw
Permalink:
http://eazon.xyz/2021/02/02/soul15/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Solgan:
Do you believe in DESTINY?