soul_admin之使用zookeeper数据同步

soul-admin修改成zookeeper的数据同步方式

参考的是项目文档https://dromara.org/zh-cn/docs/soul/user-dataSync.html

记得先启动zookeeper,我是使用docker启动的,端口是2181。

1.在soul-bootstrap的pom.xml引入依赖

<!--soul data sync start use zookeeper-->
     <dependency>
          <groupId>org.dromara</groupId>
           <artifactId>soul-spring-boot-starter-sync-data-zookeeper</artifactId>
           <version>${last.version}</version>
     </dependency>

2.如图1所示修改成zookeeper的数据同步格式

图1
图1

3.如图2修改soul-admin的配置文件

图2

4.启动admin和bootstrap,查看zookeeper的数据,可以看到会插入一个soul的目录,文件如图3所示

图3

 源码分析

全局搜索ZookeeperSyncData会找到如图4的这几个文件。主要的就是ZookeeperSyncDataService和ZookeeperSyncDataConfiguration这两个文件。另外两个是测试文件。

图4
ZookeeperSyncDataConfiguration一看就是配置类相关的,这里面注释写的很清楚,一个是注入数据同步的服务,另外一个是注册zkClient到spring的ioc容器。
public class ZookeeperSyncDataConfiguration {

    /**
     * Sync data service sync data service.
     *
     * @param zkClient          the zk client
     * @param pluginSubscriber the plugin subscriber
     * @param metaSubscribers   the meta subscribers
     * @param authSubscribers   the auth subscribers
     * @return the sync data service
     */
    @Bean
    public SyncDataService syncDataService(final ObjectProvider<ZkClient> zkClient, final ObjectProvider<PluginDataSubscriber> pluginSubscriber,
                                           final ObjectProvider<List<MetaDataSubscriber>> metaSubscribers, final ObjectProvider<List<AuthDataSubscriber>> authSubscribers) {
        log.info("you use zookeeper sync soul data.......");
        return new ZookeeperSyncDataService(zkClient.getIfAvailable(), pluginSubscriber.getIfAvailable(),
                metaSubscribers.getIfAvailable(Collections::emptyList), authSubscribers.getIfAvailable(Collections::emptyList));
    }

    /**
     * register zkClient in spring ioc.
     *
     * @param zookeeperConfig the zookeeper configuration
     * @return ZkClient {@linkplain ZkClient}
     */
    @Bean
    public ZkClient zkClient(final ZookeeperConfig zookeeperConfig) {
        return new ZkClient(zookeeperConfig.getUrl(), zookeeperConfig.getSessionTimeout(), zookeeperConfig.getConnectionTimeout());
    }

}

另外一个类是ZookeeperSyncDataService,实现了SyncDataService, AutoCloseable接口,但其实SyncDataService没有定义接口。

然后可以看到ZookeeperSyncDataService有很多方法。

我们试着关闭一个插件,然后看看调用了ZookeeperSyncDataService的watcherData()方法,原因是因为zkClient.subscribeChildChanges会触发。

private void watcherData() {
        final String pluginParent = ZkPathConstants.PLUGIN_PARENT;
        List<String> pluginZKs = zkClientGetChildren(pluginParent);
        for (String pluginName : pluginZKs) {
            watcherAll(pluginName);
        }
        zkClient.subscribeChildChanges(pluginParent, (parentPath, currentChildren) -> {
            if (CollectionUtils.isNotEmpty(currentChildren)) {
                for (String pluginName : currentChildren) {
                    watcherAll(pluginName);
                }
            }
        });
    }

打断点看到方法进到watcherAll这个方法。类似模板方法一样,查看了插件,选择器和规则有没有变化。

扫描二维码关注公众号,回复: 12419770 查看本文章
private void watcherAll(final String pluginName) {
        watcherPlugin(pluginName);
        watcherSelector(pluginName);
        watcherRule(pluginName);
    }

由于我们刚刚改变的插件,那么我们进入watcherPlugin(pluginName)这里看看

private void watcherPlugin(final String pluginName) {
        String pluginPath = ZkPathConstants.buildPluginPath(pluginName);
        //如果没有路径则注册
        if (!zkClient.exists(pluginPath)) {
            zkClient.createPersistent(pluginPath, true);
        }
        cachePluginData(zkClient.readData(pluginPath));
        subscribePluginDataChanges(pluginPath, pluginName);
    }

subscribePluginDataChanges方法如下实现了zkClient的两个方法,一个是handleDataChange更新操作,另外一个是handleDataDeleted删除操作

private void subscribePluginDataChanges(final String pluginPath, final String pluginName) {
        zkClient.subscribeDataChanges(pluginPath, new IZkDataListener() {

            @Override
            public void handleDataChange(final String dataPath, final Object data) {
                Optional.ofNullable(data)
                        .ifPresent(d -> Optional.ofNullable(pluginDataSubscriber).ifPresent(e -> e.onSubscribe((PluginData) d)));
            }

            @Override
            public void handleDataDeleted(final String dataPath) {
                final PluginData data = new PluginData();
                data.setName(pluginName);
                Optional.ofNullable(pluginDataSubscriber).ifPresent(e -> e.unSubscribe(data));
            }
        });
    }

猜你喜欢

转载自blog.csdn.net/a511310132/article/details/112976199
今日推荐