问题回顾解决
继续分析昨天boot-strap启动报错NPE的问题,提示:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nacosSyncDataService' defined in class path resource [org/dromara/soul/springboot/starter/sync/data/nacos/NacosSyncDataConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.dromara.soul.sync.data.api.SyncDataService]: Factory method 'nacosSyncDataService' threw exception; nested exception is com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException: RPC-010010015: 构造客户端代理出错!
原因是:soul-bootstrap 启动的时候会去,nacos获取网关数据,通过debugger,拿到的是空数据,使用nacos同步数据的时候,如果网关只代理http服务(无元数据),soul-bootstrap是启动不起来的。
- 去启动一下sofa服务。然后在soul-admin同步一下元数据。
- soul-admin 在系统管理-元数据管理, 点击同步数据按钮,将元数据会同步到nacos。
- 再次启动boot-strap,就提示成功啦。
2021-01-28 22:56:36.092 INFO 14652 --- [ main] d.s.s.s.s.d.n.NacosSyncDataConfiguration : you use nacos sync soul data.......
2021-01-28 22:56:37.318 INFO 14652 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2021-01-28 22:56:39.379 INFO 14652 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 9195
2021-01-28 22:56:39.394 INFO 14652 --- [ main] o.d.s.b.SoulBootstrapApplication : Started SoulBootstrapApplication in 10.686 seconds (JVM running for 16.254)
小结:soul-bootstrap 启动不起来报空指针异常,首先soul-admin启动后不会主动向nacos同步网关数据,需要手动同步,这个问题困扰了挺长时间,最后是看了其他同学的分享,才恍然大悟。
源码分析
-
数据初始化更新的时候
NacosCacheHandler
,通过调用watcherData
方法,使用Nacos提供的Listener
来注册当Nacos发布配置时候,可以监听到事件。public class NacosCacheHandler { 。。。。。。 protected void watcherData(final String dataId, final OnChange oc) { Listener listener = new Listener() { @Override public void receiveConfigInfo(final String configInfo) { oc.change(configInfo); } @Override public Executor getExecutor() { return null; } }; oc.change(getConfigAndSignListener(dataId, listener)); LISTENERS.computeIfAbsent(dataId, key -> new ArrayList<>()).add(listener); }
-
soul-admin的Nacos
配置类NacosConfiguration
#nacosConfigService
初始化bean时通过NacosFactory
创建配置服务。DataChangedEventDispatcher
负责调用具体的监听实现类对DataChangedEvent
事件进行处理,实现类NacosDataChangedListener
监听器会监听配置的变化,NacosDataChangedListener
会执行 onRuleChanged,updateRuleMap 先将网关数据同步至内存,在通过publishConfig
同步至nacos。public ConfigService nacosConfigService(final NacosProperties nacosProp) throws Exception { Properties properties = new Properties(); if (nacosProp.getAcm() != null && nacosProp.getAcm().isEnabled()) { // Use aliyun ACM service properties.put(PropertyKeyConst.ENDPOINT, nacosProp.getAcm().getEndpoint()); properties.put(PropertyKeyConst.NAMESPACE, nacosProp.getAcm().getNamespace()); // Use subaccount ACM administrative authority properties.put(PropertyKeyConst.ACCESS_KEY, nacosProp.getAcm().getAccessKey()); properties.put(PropertyKeyConst.SECRET_KEY, nacosProp.getAcm().getSecretKey()); } else { properties.put(PropertyKeyConst.SERVER_ADDR, nacosProp.getUrl()); properties.put(PropertyKeyConst.NAMESPACE, nacosProp.getNamespace()); } return NacosFactory.createConfigService(properties); }
public void onSelectorChanged(final List<SelectorData> changed, final DataEventTypeEnum eventType) { updateSelectorMap(getConfig(NacosPathConstants.SELECTOR_DATA_ID)); .。。。 publishConfig(NacosPathConstants.SELECTOR_DATA_ID, SELECTOR_MAP); }
-
soul-bootstrap 添加了nacos依赖
soul-spring-boot-starter-sync-data-nacos
,启动时自动注入类NacosSyncDataConfiguration
在初始化bean是创建了NacosSyncDataService
用于监听配置数据的变化并进行同步。public SyncDataService nacosSyncDataService(final ObjectProvider<ConfigService> configService, final ObjectProvider<PluginDataSubscriber> pluginSubscriber, final ObjectProvider<List<MetaDataSubscriber>> metaSubscribers, final ObjectProvider<List<AuthDataSubscriber>> authSubscribers) { log.info("you use nacos sync soul data......."); return new NacosSyncDataService(configService.getIfAvailable(), pluginSubscriber.getIfAvailable(), metaSubscribers.getIfAvailable(Collections::emptyList), authSubscribers.getIfAvailable(Collections::emptyList)); }
总结:
数据同步原理目前看都是类似的,下一章计划深入分析 admin 和 bootstrap的整个过程,验证下。