序
上一篇文章我们知道了 soul-admin 是怎么初始化数据库脚本的,今天我们看看另外一个核心的部分 —— 数据同步。
关于数据同步在之前的文章里已经分析过了 web socket 同步方式,但是在 soul-admin 里面除了使用 web socket 方式,还支持 http 数据同步、zookeeper 数据同步、Nacos 数据同步这三种方式。
我们先看看 soul-admin 里面的 http 数据同步吧。
soul-admin 模块里面的 http 数据同步
如果需要使用 http 数据同步的话,得在配置文件里面开启 http 数据同步的开关。
soul:
sync:
http:
enabled: true
也就上面那个 soul.sync.http.enabled 属性,设置为 true 就行了。
然后 soul-admin 会根据这个属性来选择对应的数据同步方式。代码在 DataSyncConfiguration 这个类里面。
public class DataSyncConfiguration {
@Configuration
@ConditionalOnProperty(name = "soul.sync.http.enabled", havingValue = "true")
@EnableConfigurationProperties(HttpSyncProperties.class)
static class HttpLongPollingListener {
@Bean
@ConditionalOnMissingBean(HttpLongPollingDataChangedListener.class)
public HttpLongPollingDataChangedListener httpLongPollingDataChangedListener(final HttpSyncProperties httpSyncProperties) {
return new HttpLongPollingDataChangedListener(httpSyncProperties);
}
}
}
可以看到,这个类里面关于 http 数据同步的代码就一个静态的内部类 HttpLongPollingListener。
这个类的作用就是当开启了 http 的数据同步方式之后,会启动一个 HttpLongPollingDataChangedListener 作为 http 数据同步的监听器。
接下来,我们只需要去关注这个类就知道 soul-admin 是怎么使用 http 的方式完成数据同步的了。
这个图里面我们关注的类就 4 个,其中 InitializingBean 这个接口是 Spring 框架里面的。
InitializingBean 接口为 bean 提供了属性初始化后的处理方法,它只包括 afterPropertiesSet 方法,凡是继承该接口的类,在 bean 的属性初始化后都会执行该方法。
明白接口 InitializingBean 的作用之后,我们看看它的实现类干了啥。
public abstract class AbstractDataChangedListener implements DataChangedListener, InitializingBean {
@Override
public final void afterPropertiesSet() {
updateAppAuthCache();
updatePluginCache();
updateRuleCache();
updateSelectorCache();
updateMetaDataCache();
afterInitialize();
}
}
可以看到这个实现类重写了 afterPropertiesSet 方法,主要是更新了 soul-admin 里面的一系列缓存数据。说的直白点就是从数据库里面取出「选择器」啊、「规则」啊、「元数据」啊等数据信息,存储到内存里面,最后执行 http 数据同步的初始化过程,这个过程就是 afterInitialize 方法。
那么我们继续看 afterInitialize 这个方法又干了什么。
public class HttpLongPollingDataChangedListener extends AbstractDataChangedListener {
@Override
protected void afterInitialize() {
long syncInterval = httpSyncProperties.getRefreshInterval().toMillis();
// Periodically check the data for changes and update the cache
scheduler.scheduleWithFixedDelay(() -> {
log.info("http sync strategy refresh config start.");
try {
this.refreshLocalCache();
log.info("http sync strategy refresh config success.");
} catch (Exception e) {
log.error("http sync strategy refresh config error!", e);
}
}, syncInterval, syncInterval, TimeUnit.MILLISECONDS);
log.info("http sync strategy refresh interval: {}ms", syncInterval);
}
}
可以看到上面的方法会在 HttpLongPollingDataChangedListener 这个类里面去重写,而这个类恰恰是我们最开始找到的 http 数据同步的监听器类。
转了一圈又回到了这里。这个方法干了啥呢?
从一个 httpSyncProperties 类里面取出了一个属性,然后使用定时器去定时执行 refreshLocalCache 方法, 就这么简单。
我们继续查看这个类里面的 refreshLocalCache 方法。
public class HttpLongPollingDataChangedListener extends AbstractDataChangedListener {
private void refreshLocalCache() {
this.updateAppAuthCache();
this.updatePluginCache();
this.updateRuleCache();
this.updateSelectorCache();
this.updateMetaDataCache();
}
}
怎么样,是不是觉得似曾相识?
没错,还是上面的更新缓存数据。
到了这里呢,HttpLongPollingDataChangedListener 类的基本功能就已经完成了,结合之前贴出来的类图,我们继续看 DataChangedListener 这个接口类。
public interface DataChangedListener {
default void onAppAuthChanged(List<AppAuthData> changed, DataEventTypeEnum eventType) {
}
default void onPluginChanged(List<PluginData> changed, DataEventTypeEnum eventType) {
}
default void onSelectorChanged(List<SelectorData> changed, DataEventTypeEnum eventType) {
}
default void onMetaDataChanged(List<MetaData> changed, DataEventTypeEnum eventType) {
}
default void onRuleChanged(List<RuleData> changed, DataEventTypeEnum eventType) {
}
}
可以看到这个接口就只是定义了几个事件监听的处理方法,那么它的实现类肯定会针对这些方法分别做处理。而它的实现类恰恰就是上面类图里面的 AbstractDataChangedListener 和 HttpLongPollingDataChangedListener 两个类(由于其他诸如 Zookeeper 或者 Nacos 等数据同步方式不在我们的考虑范围内)。
总结
到此为止,上面的类图涉及到的几个类都已经分析完了。
我们可以看出,以上的内容仅仅是一开始从数据库加载数据放到内存,以及定时去从数据库拉取数据更新到内存。
但是如果我在 soul-admin 可视化界面去修改了数据呢?会不会及时的同步到内存呢?
我们下篇文章再分析。