[Soul 源碼之旅] 1.7 Soul數據同步 (Nacos)

1.7.1 Nacos 簡介

Nacos 是Spring Cloud Alibaba 開源的一套分布式組件,Nacos可以作為配置中心服務和服務注冊中心,在它之前我們一般需要引入兩個組件,如 zookeeper + Apollo 這種方式,我們可以直接使用 Nacos 實現這個功能,下面是各個注冊中心的對比圖:

Nacos Eureka Consul CoreDNS Zookeeper
一致性協議 CP+AP AP CP CP
健康檢查 TCP/HTTP/MYSQL/Client Beat Client Beat TCP/HTTP/gRPC/Cmd Keep Alive
負載均衡策略 權重/ metadata/Selector Ribbon Fabio RoundRobin
雪崩保護
自動注銷實例 支持 支持 支持 不支持 支持
訪問協議 HTTP/DNS HTTP HTTP/DNS DNS TCP
監聽支持 支持 支持 支持 不支持 支持
多數據中心 支持 支持 支持 不支持 不支持
跨注冊中心同步 支持 不支持 支持 不支持 不支持
SpringCloud集成 支持 支持 支持 不支持 支持
Dubbo集成 支持 不支持 支持 不支持 支持
K8S集成 支持 不支持 支持 支持 不支持

從上面看來,Nacos 是最全面的了。

1.7.2 soul admin

目前 nacos 數據同步調試還有問題,跟蹤代碼沒找到 soul admin 初始化 數據進入 nacos 的地方,但進行修改但時候從nacos 也無法同步數據進來,報錯如下:

java.lang.NullPointerException: null
    at org.dromara.soul.admin.listener.nacos.NacosDataChangedListener.updateSelectorMap(NacosDataChangedListener.java:106) ~[classes/:na]
    at org.dromara.soul.admin.listener.nacos.NacosDataChangedListener.onSelectorChanged(NacosDataChangedListener.java:196) ~[classes/:na]
    at org.dromara.soul.admin.listener.DataChangedEventDispatcher.onApplicationEvent(DataChangedEventDispatcher.java:67) ~[classes/:na]
    at org.dromara.soul.admin.listener.DataChangedEventDispatcher.onApplicationEvent(DataChangedEventDispatcher.java:1) ~[classes/:na]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:403) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:360) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.dromara.soul.admin.service.impl.SelectorServiceImpl.createOrUpdate(SelectorServiceImpl.java:145) ~[classes/:na]
    at org.dromara.soul.admin.service.impl.SelectorServiceImpl$$FastClassBySpringCGLIB$$3dce3747.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor$$Lambda$663/387112129.proceedWithInvocation(Unknown Source) ~[na:na]
  • 2021.01.22 --- 跟蹤發現,soul admin 初始化時沒有沒有向nacos 刷入配置文件, 手工載入數據后系統正常,目前還沒找到soul 刷入nacos 數據的地方,后續更新進展。我們先來看看手工刷入數據后 nacos 的配置列表。
  • 2021.01.23 --- 更新由于代碼版本是 fork ,沒有更新最新,這個 bug 已經被修復,拉取最新版本代碼解決。問題根源還是自己對fork 代碼的流程不清晰導致,只做了 git fetch upstream ,沒有 git merge upstream/master ,具體參考鏈接,soul 不會像初始化 zookeeper一樣初始化所有數據進入 nacos ,只會在更新的時候向nacos 寫入數據。如OnSelectorchange 的方法,最后向nacos 更新全量數據。
    change

我們先來看一下 soul admin 初始化做了什么,首先初始化 bean NacosConfiguration 這里也使用了EnableConfigurationProperties 注解,注入了 NacosProperties ,然后根據 NacosProperties 調用NacosFactory.createConfigService(properties); 創建一個 nacos client 。


config

但我們修改 selector 時,會觸發 publishevent 然后調用 NacosDataChangedListener 的 onSelectorChanged。


listent

最終通過 configService 的publishConfig 發布配置信息。
image.png

我們重新查看nacos 就會出現多一個歷史版本。


image.png

1.7.3 soul bootstrap

NacosSyncDataConfiguration 是soul bootstrap 的配置入口。在初始化數據時先從nacos 取數據回來。


image.png

watcherData 會注冊配置文件修改的監聽事件, 然后通過 getConfigAndSignListener 方法向nacos 取全量數據。


image.png

當我們更新 selector 數據時,soul bootstrap 就會觸發 listener 的 onchange事件。
image.png

上面會觸發所有的 subscribe 的 unsubscribe 和 onSubscribe 操作,最后都會調用 subscribeDataHandler


image.png

這里通過BaseDataCache.getInstance().cacheSelectData(selectorData); 方法將所有內存數據更新。

1.7.4 總結

直接在 Nacos 數據同步源碼解析中印象最深刻就是 上面提到的空指針問題,需要認真學習git 整個提交RP 和 同步更新數據的流程,同時還學會使用了一些平時工作中比較少使用的代碼,如 Optional.ofNullable(pluginDataSubscriber).ifPresent (function) 這種寫法比直接使用 if else 判斷空主要優勢是代碼更簡潔,減少代碼嵌套。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容