上一篇文章我们知道了 soul-admin 是怎么初始化数据库脚本的,今天我们看看另外一个核心的部分 —— 数据同步。

关于数据同步在之前的文章里已经分析过了 web socket 同步方式,但是在 soul-admin 里面除了使用 web socket 方式,还支持 http 数据同步、zookeeper 数据同步、Nacos 数据同步这三种方式。

我们先看看 soul-admin 里面的 http 数据同步吧。

soul-admin 模块里面的 http 数据同步

如果需要使用 http 数据同步的话,得在配置文件里面开启 http 数据同步的开关。

  1. soul:
  2. sync:
  3. http:
  4. enabled: true

也就上面那个 soul.sync.http.enabled 属性,设置为 true 就行了。

然后 soul-admin 会根据这个属性来选择对应的数据同步方式。代码在 DataSyncConfiguration 这个类里面。

  1. public class DataSyncConfiguration {
  2. @Configuration
  3. @ConditionalOnProperty(name = "soul.sync.http.enabled", havingValue = "true")
  4. @EnableConfigurationProperties(HttpSyncProperties.class)
  5. static class HttpLongPollingListener {
  6. @Bean
  7. @ConditionalOnMissingBean(HttpLongPollingDataChangedListener.class)
  8. public HttpLongPollingDataChangedListener httpLongPollingDataChangedListener(final HttpSyncProperties httpSyncProperties) {
  9. return new HttpLongPollingDataChangedListener(httpSyncProperties);
  10. }
  11. }
  12. }

可以看到,这个类里面关于 http 数据同步的代码就一个静态的内部类 HttpLongPollingListener。

这个类的作用就是当开启了 http 的数据同步方式之后,会启动一个 HttpLongPollingDataChangedListener 作为 http 数据同步的监听器。

接下来,我们只需要去关注这个类就知道 soul-admin 是怎么使用 http 的方式完成数据同步的了。
image.png
这个图里面我们关注的类就 4 个,其中 InitializingBean 这个接口是 Spring 框架里面的。

InitializingBean 接口为 bean 提供了属性初始化后的处理方法,它只包括 afterPropertiesSet 方法,凡是继承该接口的类,在 bean 的属性初始化后都会执行该方法。

明白接口 InitializingBean 的作用之后,我们看看它的实现类干了啥。

  1. public abstract class AbstractDataChangedListener implements DataChangedListener, InitializingBean {
  2. @Override
  3. public final void afterPropertiesSet() {
  4. updateAppAuthCache();
  5. updatePluginCache();
  6. updateRuleCache();
  7. updateSelectorCache();
  8. updateMetaDataCache();
  9. afterInitialize();
  10. }
  11. }

可以看到这个实现类重写了 afterPropertiesSet 方法,主要是更新了 soul-admin 里面的一系列缓存数据。说的直白点就是从数据库里面取出「选择器」啊、「规则」啊、「元数据」啊等数据信息,存储到内存里面,最后执行 http 数据同步的初始化过程,这个过程就是 afterInitialize 方法。

那么我们继续看 afterInitialize 这个方法又干了什么。

  1. public class HttpLongPollingDataChangedListener extends AbstractDataChangedListener {
  2. @Override
  3. protected void afterInitialize() {
  4. long syncInterval = httpSyncProperties.getRefreshInterval().toMillis();
  5. // Periodically check the data for changes and update the cache
  6. scheduler.scheduleWithFixedDelay(() -> {
  7. log.info("http sync strategy refresh config start.");
  8. try {
  9. this.refreshLocalCache();
  10. log.info("http sync strategy refresh config success.");
  11. } catch (Exception e) {
  12. log.error("http sync strategy refresh config error!", e);
  13. }
  14. }, syncInterval, syncInterval, TimeUnit.MILLISECONDS);
  15. log.info("http sync strategy refresh interval: {}ms", syncInterval);
  16. }
  17. }

可以看到上面的方法会在 HttpLongPollingDataChangedListener 这个类里面去重写,而这个类恰恰是我们最开始找到的 http 数据同步的监听器类。

转了一圈又回到了这里。这个方法干了啥呢?

从一个 httpSyncProperties 类里面取出了一个属性,然后使用定时器去定时执行 refreshLocalCache 方法, 就这么简单。

我们继续查看这个类里面的 refreshLocalCache 方法。

  1. public class HttpLongPollingDataChangedListener extends AbstractDataChangedListener {
  2. private void refreshLocalCache() {
  3. this.updateAppAuthCache();
  4. this.updatePluginCache();
  5. this.updateRuleCache();
  6. this.updateSelectorCache();
  7. this.updateMetaDataCache();
  8. }
  9. }

怎么样,是不是觉得似曾相识?

没错,还是上面的更新缓存数据。

到了这里呢,HttpLongPollingDataChangedListener 类的基本功能就已经完成了,结合之前贴出来的类图,我们继续看 DataChangedListener 这个接口类。

  1. public interface DataChangedListener {
  2. default void onAppAuthChanged(List<AppAuthData> changed, DataEventTypeEnum eventType) {
  3. }
  4. default void onPluginChanged(List<PluginData> changed, DataEventTypeEnum eventType) {
  5. }
  6. default void onSelectorChanged(List<SelectorData> changed, DataEventTypeEnum eventType) {
  7. }
  8. default void onMetaDataChanged(List<MetaData> changed, DataEventTypeEnum eventType) {
  9. }
  10. default void onRuleChanged(List<RuleData> changed, DataEventTypeEnum eventType) {
  11. }
  12. }

可以看到这个接口就只是定义了几个事件监听的处理方法,那么它的实现类肯定会针对这些方法分别做处理。而它的实现类恰恰就是上面类图里面的 AbstractDataChangedListener 和 HttpLongPollingDataChangedListener 两个类(由于其他诸如 Zookeeper 或者 Nacos 等数据同步方式不在我们的考虑范围内)。

总结

到此为止,上面的类图涉及到的几个类都已经分析完了。

我们可以看出,以上的内容仅仅是一开始从数据库加载数据放到内存,以及定时去从数据库拉取数据更新到内存。

但是如果我在 soul-admin 可视化界面去修改了数据呢?会不会及时的同步到内存呢?

我们下篇文章再分析。