Soul中使用的zookeeper監聽功能嘗試和nacos同步源碼解讀

Soul中使用的zookeeper監聽功能嘗試

一直很好奇soul中基於zookeeper的數據變更是如何做到的。雖然看到了是基於zkClient的實現的,還是想自己嘗試下

zookeeper監聽嘗試

首先新建一個maven項目,引入zkClient

        <dependency>
           <groupId>com.101tec</groupId>
           <artifactId>zkclient</artifactId>
           <version>0.10</version>
       </dependency>

嘗試着對zokkeeper中的數據和節點做一些改變,而這個改變就是Soul使用zookeeper中對於插件,選擇器和規則變化將其映射到zookeeper上的結果

public class ZkClientTest {


   public static final String connect = "127.0.0.1:2181";
   private static ZkClient zkClient = null;
   private static String nodePath = "/zkclient1";
   private static String nodeChildPath = "/zkclient1/n1/n11/n111/n1111";
   public static void main(String[] args) throws Exception{
       //初始化
       init(connect,5000);

       //訂閱節點數據改變或者子節點變化,只需要訂閱一次,便可以一直使用。而原生zookeeper的監聽是一次性的,需要重複註冊。
       subscribe();

       //新增
       create(nodePath,"n1");
       //遞歸新增
       createRecursion(nodeChildPath,"n1");

       //查詢
       query(nodePath);

       //修改
       update(nodePath,"n11");

       //單個節點刪除
//        delete(nodePath);
       //遞歸刪除
       deleteRecursion(nodePath);


       Thread.sleep(5000);
   }

   private static void deleteRecursion(String path) {
       boolean result = zkClient.deleteRecursive(path);
       System.out.println("delete:"+"["+path+"],result:"+result);
   }

   private static void delete(String path) {
       boolean result = zkClient.delete(path);
       System.out.println("delete:"+"["+path+"],result:"+result);
   }

   private static void update(String path, String data) {
       zkClient.writeData(path, data);
       System.out.println();
       //System.out.println("setData:"+"["+path+"],stat:"+stat);
   }

   private static void query(String path) {
       Object o = zkClient.readData(path);
       System.out.println("query:"+"["+path+"],result:"+o);
   }

   private static void createRecursion(String path,String data)  {
       zkClient.createPersistent(path,true);
       System.out.println("create:"+"["+path+"-->"+data);
   }

   private static void create(String path, String data) {
       boolean exists = zkClient.exists(path);
       if(exists){
           System.out.println("節點["+path+"]已存在,不能新增");
           return;
       }
       String result = zkClient.create(path, data, CreateMode.PERSISTENT);
       System.out.println("create:"+"["+path+"-->"+data+"],result:"+result);
   }

   private static void subscribe() {
       //訂閱節點內容改變
       zkClient.subscribeDataChanges(nodePath, new IZkDataListener() {
                   public void handleDataChange(String dataPath, Object data) throws Exception {
                       System.out.println("handleDataChange----->"+dataPath+"|"+data);
                   }

                   public void handleDataDeleted(String dataPath) throws Exception {
                       System.out.println("handleDataDeleted----->"+dataPath);
                   }
               }
       );

       //訂閱子節點改變
       zkClient.subscribeChildChanges(nodePath, new IZkChildListener() {
           public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
               System.out.println("handleChildChange----->"+parentPath+"|"+currentChilds);
           }
       });

   }

   private static void init(String connect, int sessionTimeout) {
       zkClient = new ZkClient(connect, sessionTimeout);
   }
}

具體的日誌表現如下圖所示
file
而在具體的zKclient類中可以看到,zkclient實際上是維護了一個while循環用來監聽數據以及節點的變化
file
這就是Soul在ZookeeperDataChangedListener實際使用的具體的時候的具體使用的方案
file

Soul中Nacos是如何監聽數據變化的

nacos的監聽與zk類似,soul中的nacos一開始就監聽了soul各個層級的數據的變化

  /**
     * Start.
     */
    public void start() {
        watcherData(PLUGIN_DATA_ID, this::updatePluginMap);
        watcherData(SELECTOR_DATA_ID, this::updateSelectorMap);
        watcherData(RULE_DATA_ID, this::updateRuleMap);
        watcherData(META_DATA_ID, this::updateMetaDataMap);
        watcherData(AUTH_DATA_ID, this::updateAuthMap);
    }

然後通過函數式編程的方式將數據通過各個方法更新到緩存中

    protected void watcherData(final String dataId, final OnChange oc) {
        Listener listener = new Listener() {
            @Override
            public void receiveConfigInfo(final String configInfo) {
                oc.change(configInfo);
            }

            @Override
            public Executor getExecutor() {
                return null;
            }
        };
        oc.change(getConfigAndSignListener(dataId, listener));
        LISTENERS.getOrDefault(dataId, new ArrayList<>()).add(listener);
    }

這裏的最關鍵是Listener接口的獲取配置信息的兩個方法。可以看到這個即是通過預先定義號的元數據id,規則id來進行監聽數據是否發生變化的

上面就是nacos和zookeeper監聽數據變化的過程,現在可以想到。不管是配置中心或者註冊中心。數據變化的監聽都是有必要的,可以爲使用的應用做出跟隨配置改變而改變應用邏輯的能力。這也是Soul網關中很重要的一項能力

歡迎搜索關注本人與朋友共同開發的微信面經小程序【大廠面試助手】和公衆號【微瞰技術】,以及總結的分類面試題https://github.com/zhendiao/JavaInterview

file
file

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章