zookeeper zkClient客戶端

前言

GitHub:https://github.com/yihonglei/ZooKeeper-Study

本文采用zk原生客戶端方式對zk進行操作,對應github的zk-client項目。

maven引入jar包:

<dependency>
   <groupId>org.apache.zookeeper</groupId>
   <artifactId>zookeeper</artifactId>
   <version>3.4.14</version>
</dependency>

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

一 zkClient

ZkClient 是由 Datameer 的工程師開發的開源客戶端,對 Zookeeper 的原生 API 進行了包 裝,實現了超時重連、

Watcher 反覆註冊等功能。

二 zkClient操作znode

實例代碼:

package com.lanhuigu.zookeeper.znode;

import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;

import java.io.Serializable;
import java.util.List;

/**
 * ZkClient 進行CRUD操作。
 *
 * @auther: yihonglei
 * @date: 2019-05-14 17:09
 */
public class ZkClientCrud<T> {
    private String connectString = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183";
    private ZkClient zkClient;

    public ZkClientCrud() {
        this.zkClient = new ZkClient(connectString, 5000,
                5000, new SerializableSerializer());
    }

    /**
     * 創建持久節點
     */
    public void createPersistent(String path, Object data) {

        zkClient.createPersistent(path, data);
    }

    /**
     * 遞歸創建持久節點
     */
    public void createPersistent(String path, boolean createParents) {

        zkClient.createPersistent(path, createParents);
    }

    /**
     * 讀取信息
     */
    public T readData(String path) {

        return zkClient.readData(path);
    }

    /**
     * 獲取子節點列表
     */
    public List<String> getChildren(String path) {

        return zkClient.getChildren(path);
    }

    /**
     * 數據寫入節點
     */
    public void writeData(String path, Object object) {

        zkClient.writeData(path, object);
    }

    /**
     * 刪除節點
     */
    public void delete(String path) {

        zkClient.delete(path);
    }

    /**
     * 判斷節點是否存在
     */
    public boolean exists(String path) {

        return zkClient.exists(path);
    }

    /**
     * 遞歸刪除節點
     */
    public void deleteRecursive(String path) {

        zkClient.deleteRecursive(path);
    }

    /**
     * 用戶實體,需要序列化
     */
    public static class User implements Serializable {
        private String userName;
        private String password;

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        @Override
        public String toString() {
            return "User{" +
                    "userName='" + userName + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    }

    /**
     * 測試
     */
    public static void main(String[] args) {
        ZkClientCrud client = new ZkClientCrud();

        // ------ 1、存儲單個值 -------
        String path = "/lanhuiguZkClient";

        // 判斷節點是否存在
        if (client.exists(path)) {
            client.delete(path);
        }

        // 創建節點
        client.createPersistent(path, "2019");

        // 讀取數據
        String data = client.readData(path).toString();
        System.out.println("存儲單個值readData:" + data);


        // ------ 2、存儲對象 -------
        String pathObj = "/lanhuiguZkClientObj";

        // 判斷節點是否存在
        if (client.exists(pathObj)) {
            client.delete(pathObj);
        }

        // 創建節點
        User user = new User();
        user.setUserName("root");
        user.setPassword("123456");

        client.createPersistent(pathObj, user);

        // 讀取數據
        System.out.println("存儲對象readData:" + client.readData(pathObj));

    }
}

三 zkClient操作watcher

zkClient封裝了三種重要的註冊監聽。

接口類 註冊監聽方法 解除監聽方法 

IZkChildListener

(子節點)

ZkClient 的 subscribeChildChanges 方法

ZkClient 的 unsubscribeChildChanges 方法

IZkDataListener

(數據)

ZkClient 的 subscribeDataChanges 方法

ZkClient 的 unsubscribeDataChanges 方法

IZkStateListener

(客戶端狀 態)

ZkClient 的 subscribeStateChanges 方 法

ZkClient 的 unsubscribeStateChanges 方法

在 ZkClient 中客戶端可以通過註冊相關的事件監聽來實現對 Zookeeper 服務端時間的訂閱。

package com.lanhuigu.zookeeper.watcher;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.IZkStateListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;
import org.apache.zookeeper.Watcher;

import java.util.List;

/**
 * ZkClient 進行watcher操作。
 *
 * @auther: yihonglei
 * @date: 2019-05-14 17:09
 */
public class ZkClientWatcher<T> {
    private String connectString = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183";
    private ZkClient zkClient;

    public ZkClientWatcher() {
        this.zkClient = new ZkClient(connectString, 5000, 5000, new SerializableSerializer());
    }

    /**
     * 讀取信息
     */
    public T readData(String path) {
        return zkClient.readData(path);

    }

    /**
     * 獲取子節點列表
     */
    public List<String> getChildren(String path) {
        return zkClient.getChildren(path);

    }

    /**
     * 數據寫入節點
     */
    public void writeData(String path, Object object) {
        zkClient.writeData(path, object);

    }

    /**
     * 創建持久節點
     */
    public void createPersistent(String path, Object data) {
        zkClient.createPersistent(path, data);
    }

    /**
     * 遞歸創建持久節點
     */
    public void createPersistent(String path, boolean createParents) {

        zkClient.createPersistent(path, createParents);
    }

    /**
     * 判斷節點是否存在
     */
    public boolean exists(String path) {

        return zkClient.exists(path);
    }

    /**
     * 刪除節點
     */
    public void delete(String path) {

        zkClient.delete(path);
    }

    /**
     * 遞歸刪除節點
     */
    public void deleteRecursive(String path) {

        zkClient.deleteRecursive(path);
    }

    /**
     * 節點添加監聽
     */
    public void listener(String path) {
        // 對當前節點數據改變進行監聽
        zkClient.subscribeDataChanges(path, new IZkDataListener() {
            @Override
            public void handleDataChange(String dataPath, Object data) throws Exception {
                System.out.println("【變更節點】dataPath: " + dataPath + ", data: " + data);
            }

            @Override
            public void handleDataDeleted(String dataPath) throws Exception {
                System.out.println("【刪除節點】dataPath: " + dataPath);
            }
        });

        // 對當前節點的子節點改變進行監聽
        zkClient.subscribeChildChanges(path, new IZkChildListener() {
            @Override
            public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
                System.out.println("【子節點改變監聽】parentPath: " + parentPath + ", currentChilds: " + currentChilds);
            }
        });

        // 對當前節點狀態變化進行監聽
        zkClient.subscribeStateChanges(new IZkStateListener() {
            @Override
            public void handleStateChanged(Watcher.Event.KeeperState state) throws Exception {
                if (state == Watcher.Event.KeeperState.SyncConnected) {
                    // 當重新啓動後start,監聽觸發
                    System.out.println("連接成功");
                } else if (state == Watcher.Event.KeeperState.Disconnected) {
                    System.out.println("連接斷開");// 當在服務端將zk服務stop時,監聽觸發
                } else {
                    System.out.println("其他狀態" + state);
                }
            }

            @Override
            public void handleNewSession() throws Exception {
                System.out.println("重建session");
            }

            @Override
            public void handleSessionEstablishmentError(Throwable error) throws Exception {
            }
        });
    }

    /**
     * 測試代碼
     */
    public static void main(String[] args) throws InterruptedException {
        ZkClientWatcher zkClientWatcher = new ZkClientWatcher();

        String path = "/lanhuiguZkClientWatcher";

        // 啓動監聽
        zkClientWatcher.listener(path);

        // 刪除節點
        if (zkClientWatcher.exists(path)) {
            zkClientWatcher.deleteRecursive(path);
        }

        // 創建節點
        zkClientWatcher.createPersistent(path, "2019");

        // 休眠
        Thread.sleep(2000);

        // 寫操作
        zkClientWatcher.writeData(path, "2019-new");

        // 讓主線程一直休眠,不斷掉
        Thread.sleep(Integer.MAX_VALUE);
    }
}

監聽處理註冊後,節點發生改變,觸發相應的事件。

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