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 判断空主要优势是代码更简洁,减少代码嵌套。