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

监听处理注册后,节点发生改变,触发相应的事件。

发布了502 篇原创文章 · 获赞 358 · 访问量 118万+

猜你喜欢

转载自blog.csdn.net/yhl_jxy/article/details/90315575