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 。
但我們修改 selector 時,會觸發 publishevent 然后調用 NacosDataChangedListener 的 onSelectorChanged。
最終通過 configService 的publishConfig 發布配置信息。
我們重新查看nacos 就會出現多一個歷史版本。
1.7.3 soul bootstrap
NacosSyncDataConfiguration 是soul bootstrap 的配置入口。在初始化數據時先從nacos 取數據回來。
watcherData 會注冊配置文件修改的監聽事件, 然后通過 getConfigAndSignListener 方法向nacos 取全量數據。
當我們更新 selector 數據時,soul bootstrap 就會觸發 listener 的 onchange事件。
上面會觸發所有的 subscribe 的 unsubscribe 和 onSubscribe 操作,最后都會調用 subscribeDataHandler
這里通過BaseDataCache.getInstance().cacheSelectData(selectorData); 方法將所有內存數據更新。
1.7.4 總結
直接在 Nacos 數據同步源碼解析中印象最深刻就是 上面提到的空指針問題,需要認真學習git 整個提交RP 和 同步更新數據的流程,同時還學會使用了一些平時工作中比較少使用的代碼,如 Optional.ofNullable(pluginDataSubscriber).ifPresent (function) 這種寫法比直接使用 if else 判斷空主要優勢是代碼更簡潔,減少代碼嵌套。