This article mainly introduces the application of Watch mechanism in the Synchronization strategy of ZooKeeper in soul framework.

background

【8】- ZooKeeper synchronization in the Soul gateway framework to use ZooKeeper for data synchronization, this article will understand the watch mechanism principle of ZooKeeper.

Watch mechanism principle

  • The WATCH mechanism of ZK is to monitor the nodes created on ZK and generate watch events when the data changes and send them to the client.

  • The main process of watch mechanism is as follows:

    • The client registers watcher
    • The server data changes
    • The server notifies the client of data changes
    • The client calls back watcher to handle the change logic

Zookeeper synchronization mechanism source code analysis

soul-adminSide ZK synchronous source code analysis (server)

  • Introduction of zkClient dependency package;

    <dependency> <groupId>com.101tec</groupId> <artifactId> zkClient </artifactId> <version>0.10</version> </dependency>Copy the code
  • Instantiation zkClient;

    // ZookeeperConfiguration.java
    @Bean
    @ConditionalOnMissingBean(ZkClient.class)
    public ZkClient zkClient(final ZookeeperProperties zookeeperProp) {
        return new ZkClient(zookeeperProp.getUrl(), zookeeperProp.getSessionTimeout(), zookeeperProp.getConnectionTimeout());
    }
    Copy the code
  • Soul-admin creates a node at startup, where selector and rule nodes are deleted and rebuilt if created, and then data is written, but plug-in nodes are not.

    // ZookeeperDataInit.java @Override public void run(final String... args) { String pluginPath = ZkPathConstants.PLUGIN_PARENT; String authPath = ZkPathConstants.APP_AUTH_PARENT; String metaDataPath = ZkPathConstants.META_DATA; if (! zkClient.exists(pluginPath) && ! zkClient.exists(authPath) && ! zkClient.exists(metaDataPath)) { syncDataService.syncAll(DataEventTypeEnum.REFRESH); }}Copy the code
    // SyncDataServiceImpl.java
    public boolean syncAll(final DataEventTypeEnum type) {
        //...
         List<SelectorData> selectorDataList = selectorService.listAll();
         eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.SELECTOR, type, selectorDataList));
        // ...
    }
    Copy the code
  • Released by eventPublisher events to ZookeeperDataChangedListener processing;

    public void onSelectorChanged(final List<SelectorData> changed, Final DataEventTypeEnum eventType) {/ / system startup is to REFRESH the event if (eventType = = DataEventTypeEnum. REFRESH) {final String selectorParentPath = ZkPathConstants.buildSelectorParentPath(changed.get(0).getPluginName()); // Delete all children recursively deleteZkPathRecursive(selectorParentPath); } for (SelectorData data : changed) { final String selectorRealPath = ZkPathConstants.buildSelectorRealPath(data.getPluginName(), data.getId()); if (eventType == DataEventTypeEnum.DELETE) { deleteZkPath(selectorRealPath); continue; } final String selectorParentPath = ZkPathConstants.buildSelectorParentPath(data.getPluginName()); CreateZkNode (selectorParentPath); // Write node data upsertZkNode(selectorRealPath, data); }}Copy the code

soul-bootstrapSide ZK synchronous source code analysis (client)

  • Introduction of zkClient dependency package;

    <dependency> <groupId>com.101tec</groupId> <artifactId> zkClient </artifactId> <version>0.10</version> </dependency>Copy the code
  • Instantiation zkClient;

    // ZookeeperSyncDataConfiguration.java
    
    @Bean
    public ZkClient zkClient(final ZookeeperConfig zookeeperConfig) {
        return new ZkClient(zookeeperConfig.getUrl(), zookeeperConfig.getSessionTimeout(), zookeeperConfig.getConnectionTimeout());
    }
    Copy the code
    // ZookeeperConfig.java
    @Data
    @ConfigurationProperties(prefix = "soul.sync.zookeeper")
    public class ZookeeperConfig {
    
        private String url;
    
        private Integer sessionTimeout;
    
        private Integer connectionTimeout;
    
        private String serializer;
    }
    Copy the code
  • Soul-bootstrap monitors nodes during startup.

    private void watcherAll(final String pluginName) {
        watcherPlugin(pluginName);
        watcherSelector(pluginName);
        watcherRule(pluginName);
    }
    Copy the code
  • Take the plug-in node as an example:

    private void watcherPlugin(final String pluginName) { String pluginPath = ZkPathConstants.buildPluginPath(pluginName); if (! zkClient.exists(pluginPath)) { zkClient.createPersistent(pluginPath, true); } // cachePluginData(zkclient.readData (pluginPath)); / / to monitor node change subscribePluginDataChanges (pluginPath pluginName); }Copy the code

series

  • Soul source learning [1] – preliminary exploration
  • Soul source learning [2] – divide load balancing plug-in
  • Soul source learning [3] – Dubbo plug-in
  • Soul source learning [4] – RateLimiter stream limiting plug-in
  • Soul source learning [5] – SpringCloud plug-in
  • Soul source learning [6] – Chain of responsibility mode
  • Soul source learning [7] – Data synchronization strategy websocket synchronization
  • [8] – Data synchronization strategy for ZooKeeper synchronization