前言
昨天調(diào)試的時候大脉,發(fā)現(xiàn) listeners 中包含 WebsocketDataChangedListener
。
那這個是怎么來的呢术裸?今天就初探數(shù)據(jù)同步原理。
同步策略概要
官網(wǎng)上有張關于同步數(shù)據(jù)的高清無碼的大圖枯跑。
從這張大圖上我們大體知道,soul-admin 配置后怎么同步到 soul-bootstrap 層生效的白热。
之前我們也了解過
ApplicationEventPublisher
和 DataChangedEventDispatcher
敛助,寫了一個關于怎么使用 ApplicationEventPublisher
簡單的 demo ,然后又通過 Debug 我們驗證配置流程
繼續(xù)調(diào)試
當進入 DataChangedEventDispatcher#onApplicationEvent 的方法時屋确,具體方法如下:
@Override
@SuppressWarnings("unchecked")
public void onApplicationEvent(final DataChangedEvent event) {
for (DataChangedListener listener : listeners) {
switch (event.getGroupKey()) {
case APP_AUTH:
listener.onAppAuthChanged((List<AppAuthData>) event.getSource(), event.getEventType());
break;
case PLUGIN:
listener.onPluginChanged((List<PluginData>) event.getSource(), event.getEventType());
break;
case RULE:
listener.onRuleChanged((List<RuleData>) event.getSource(), event.getEventType());
break;
case SELECTOR:
listener.onSelectorChanged((List<SelectorData>) event.getSource(), event.getEventType());
break;
case META_DATA:
listener.onMetaDataChanged((List<MetaData>) event.getSource(), event.getEventType());
break;
default:
throw new IllegalStateException("Unexpected value: " + event.getGroupKey());
}
}
}
@Override
// afterPropertiesSet方法纳击,初始化bean的時候執(zhí)行,可以針對某個具體的bean進行配置乍恐。
public void afterPropertiesSet() {
Collection<DataChangedListener> listenerBeans = applicationContext.getBeansOfType(DataChangedListener.class).values();
this.listeners = Collections.unmodifiableList(new ArrayList<>(listenerBeans));
}
首先映入眼簾的是循環(huán)變量 listeners评疗, 查看得知 listeners 的類型是
List<DataChangedListener>
, 其中 DataChangedListener 是其元素的類型茵烈, 然后繼續(xù)追蹤 DataChangedListener百匆;
發(fā)現(xiàn)它是一個接口,并非是實現(xiàn)呜投,他的實現(xiàn)有
-
HttpLongPollingDataChangedListener
http的長輪詢 -
NacosDataChangedListener
nacos 配置中心 -
WebsocketDataChangedListener
websocket 的方式 -
ZookeeperDataChangedListener
zk 配置中心(這個配置中心能dubbo 的共用么加匈?)
那這些實現(xiàn)又是怎么注冊到應用中的呢?
看這里的時候有點懵仑荐,然后我重新啟動應用: SoulBootstrapApplication, 在命令行中發(fā)現(xiàn) you use websocket sync soul data
, 全文檢索雕拼,得到以下方法:
@Bean
public SyncDataService websocketSyncDataService(final ObjectProvider<WebsocketConfig> websocketConfig, final ObjectProvider<PluginDataSubscriber> pluginSubscriber,
final ObjectProvider<List<MetaDataSubscriber>> metaSubscribers, final ObjectProvider<List<AuthDataSubscriber>> authSubscribers) {
log.info("you use websocket sync soul data.......");
return new WebsocketSyncDataService(websocketConfig.getIfAvailable(WebsocketConfig::new), pluginSubscriber.getIfAvailable(),
metaSubscribers.getIfAvailable(Collections::emptyList), authSubscribers.getIfAvailable(Collections::emptyList));
}
該方法所在類上有這么一個注解
@ConditionalOnProperty(prefix = "soul.sync.websocket", name = "urls")
在 配置文件中:application-local.yml
中 配置
soul :
sync:
websocket :
urls: ws://localhost:9095/websocket
這樣的配置在啟動時就嘗試去連接了,soul-admin 中 websocket 服務器粘招。
然后我們繼續(xù)看 soul-admin, 同理推想是不是已經(jīng)在啟動時注冊了啥寇,查看配置文件
application.yml
,
soul:
sync:
websocket:
enabled: true
查看 DataSyncConfiguration
@Configuration
@ConditionalOnProperty(name = "soul.sync.websocket.enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(WebsocketSyncProperties.class)
static class WebsocketListener {
/**
* Config event listener data changed listener.
*
* @return the data changed listener
*/
@Bean
@ConditionalOnMissingBean(WebsocketDataChangedListener.class)
public DataChangedListener websocketDataChangedListener() {
return new WebsocketDataChangedListener();
}
/**
* Websocket collector websocket collector.
*
* @return the websocket collector
*/
@Bean
@ConditionalOnMissingBean(WebsocketCollector.class)
public WebsocketCollector websocketCollector() {
return new WebsocketCollector();
}
/**
* Server endpoint exporter server endpoint exporter.
*
* @return the server endpoint exporter
*/
@Bean
@ConditionalOnMissingBean(ServerEndpointExporter.class)
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
注冊了 WebsocketDataChangedListener
。到此同步策略怎么來的已經(jīng)走完了洒扎。大體的流程圖如下:
總結
- 目前還是只看了大體的流程辑甜。一些細節(jié)的地方還需要在斟酌斟酌。
- 針對以上內(nèi)容袍冷,還需要看非 Soul 上的 afterPropertiesSet, spring-bean模塊中InitializingBean接口
- 接下來要看的地方就是數(shù)據(jù)同步的具體實現(xiàn)