Soul网关(七)---- zookeeper同步数据

开启zookeeper数据同步

1.soul-bootstrap引入soul-spring-boot-starter-sync-data-zookeeper依赖:

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

2.在soul-bootstrap中添加zookeeper的配置:

        zookeeper:
             url: localhost:2181
             sessionTimeout: 5000
             connectionTimeout: 2000

3.soul-admin中开启zk同步数据

soul:
  database:
    dialect: mysql
    init_script: "META-INF/schema.sql"
  sync:
#    websocket:
#      enabled: true
      zookeeper:
          url: localhost:2181
          sessionTimeout: 5000
          connectionTimeout: 2000

zookeeper 数据同步原理

基于 zookeeper 的同步原理很简单,主要是依赖 zookeeper 的 watch 机制,soul-web 会监听配置的节点,soul-admin 在启动的时候,会将数据全量写入 zookeeper,后续数据发生变更时,会增量更新 zookeeper 的节点,与此同时,soul-bootstrap中引入的soul-spring-boot-starter-sync-data-zookeeper 会监听配置信息的节点,一旦有信息变更时,会更新本地缓存。

soul-admin 通过 zkClient 发送数据变化?

ZookeeperDataChangedListener 类实现了 DataChangedListener接口,监听数据的变化,并通过zkClient将数据的变化增量更新到 zookeeper的节点.

	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());
            }
        }
    }

Zookeeper 监听器的初始化:

 		/**
     * The type Zookeeper listener.
     */
    @Configuration
    @ConditionalOnProperty(prefix = "soul.sync.zookeeper", name = "url")
    @Import(ZookeeperConfiguration.class)
    static class ZookeeperListener {

        /**
         * Config event listener data changed listener.
         *
         * @param zkClient the zk client
         * @return the data changed listener
         */
        @Bean
        @ConditionalOnMissingBean(ZookeeperDataChangedListener.class)
        public DataChangedListener zookeeperDataChangedListener(final ZkClient zkClient) {
            return new ZookeeperDataChangedListener(zkClient);
        }

        /**
         * Zookeeper data init zookeeper data init.
         *
         * @param zkClient        the zk client
         * @param syncDataService the sync data service
         * @return the zookeeper data init
         */
        @Bean
        @ConditionalOnMissingBean(ZookeeperDataInit.class)
        public ZookeeperDataInit zookeeperDataInit(final ZkClient zkClient, final SyncDataService syncDataService) {
            return new ZookeeperDataInit(zkClient, syncDataService);
        }
    }

soul-bootstrap 订阅zk数据的变化并处理

soul-spring-boot-starter-sync-data-zookeeper 作为 starter 被 soul-bootstrap 引入。

spring.factories 文件中指定了自动配置类 ZookeeperSyncDataConfiguration:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.dromara.soul.spring.boot.sync.data.zookeeper.ZookeeperSyncDataConfiguration

ZookeeperSyncDataConfiguration 中自动装载bean时,创建了 zookeeper 客户端对象,以及 ZookeeperSyncDataService对象,

ZookeeperSyncDataService 会监听 zookeeper中选择器、规则、元数据、用户权限等数据的变更。如何监听?----通过zookeeper 客户端订阅zookeeper数据的变化,实现监听并处理变化的数据.

  // 订阅zookeeper数据的变化实现监听
	public void subscribeDataChanges(String path, IZkDataListener listener) {
        synchronized(this._dataListener) {
            Set<IZkDataListener> listeners = (Set)this._dataListener.get(path);
            if (listeners == null) {
                listeners = new CopyOnWriteArraySet();
                this._dataListener.put(path, listeners);
            }

            ((Set)listeners).add(listener);
        }

        this.watchForData(path);
        LOG.debug("Subscribed data changes for " + path);
    }

总结

参考:Apache ZooKeeper Watcher 机制源码解释

ZooKeeper 允许客户端向服务端注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。

ZooKeeper 的 Watcher 机制主要包括客户端线程、客户端 WatchManager 和 ZooKeeper 服务器三部分。在具体工作流程上,简单地讲,客户端在向 ZooKeeper 服务器注册 Watcher 的同时,会将 Watcher 对象存储在客户端的 WatchManager 中。当 ZooKeeper 服务器端触发 Watcher 事件后,会向客户端发送通知,客户端线程从 WatchManager 中取出对应的 Watcher 对象来执行回调逻辑

图 1. Watcher 注册和通知流程图
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值