Skip to content

Zookeeper管阀提供了java客户端操作Zookeeper的API,但是并不好用,我们使用大神封装好的ZKClient客户端操作Zookeeper,一篇文章即可上手。

xml
<dependency>
    <groupId>com.github.sgroschupf</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.1</version>
</dependency>

初始化ZClient

就两个参数,ip地址加端口号以及连接超时时间。

java
ZkClient zkClient = new ZkClient("192.168.31.76:2181", 50000);

创建节点

createParents用于创建节点,支持直接写路径递归创建子节点,且节点内容可以传任意类型数据,可以自定义内容的序列化和反序列化。在没指定zkSerializer时,默认使用java自动的序列化和反序列化

java
package cn.lxm.attendance.controller;
 
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkConnection;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.ZkConnection;
import org.apache.zookeeper.CreateMode; 
import java.util.List;
 

public class ZkClientTest {
    private static final String PATH = "/xk857/test";
    static ZkClient zkClient = new ZkClient("192.168.31.76:2181",50000);
 
    public static void main(String[] args) throws InterruptedException {
        createNode();
        List<String> children = zkClient.getChildren("/");
        System.out.println(children);
    }
 
    // 创建node
    public static void createNode(){
        
        // 创建一个永久的node节点a
        zkClient.createPersistent("/a");
 
        // 创建一个永久性node节点b,和原生API相似直接传递数据进去,CreateMode有四种取值
        zkClient.create("/b","这里是内容", CreateMode.PERSISTENT);
 
        // 创建一个永久性node节点c/cc,true代表可以递归创建
        zkClient.createPersistent("/c/cc",true);
 
        // 创建永久性node节点d,里面内容为‘内容d’
        zkClient.createPersistent("/d","内容d");
 
        // 创建一个临时节点f
        zkClient.createEphemeral("/f");
 
        // 创建一个临时节点g,内容为  ‘内容g’
        zkClient.createEphemeral("/g","内容g");
 
        // 创建一个  递增序号  临时节点h
        zkClient.createEphemeralSequential("/h","内容h");
 
        // 创建一个  递增序号  的永久节点i
        zkClient.createPersistentSequential("/i","内容i");
    }
}
  • CreateMode
    • PERSISTENT:持久节点。如果节点不存在,则创建该节点;如果节点已经存在,则抛出异常。
    • EPHEMERAL:临时节点。如果节点不存在,则创建该节点;如果节点已经存在,则删除该节点和其所有子节点。
    • EPHEMERAL_SEQUENTIAL:顺序临时节点。与EPHEMERAL类似,但如果节点已经存在,则在当前节点之后创建一个新节点。
    • EPHEMERAL_ALLOFTHEABOVE:以上三种节点类型的组合。即同时具有PERSISTENTEPHEMERALEPHEMERAL_SEQUENTIAL节点的特性

删除节点

deleteRecursive可以递归删除节点下所有的子节点

java
public static void deleteNode(){
    // 删除节点c,以及节点c下面所有的子节点
    zkClient.deleteRecursive("/c");
}

ZKClient注册监听

  • subscribeChildChanges:在节点上加上一个listen监听事件,用来监听子节点的变化
  • subscribeDataChanges:监听当前节点上数据的变化;handleDataChange数据变化, handleDataDeleted节点数据被删除
  • subscribeStateChanges:监听zookeeper的状态
java
// 注册一个监听事件,subscribeChildChanges,通过使用listen方式来监听来达到消息广播效果,监听子节点变化
zkClient.subscribeChildChanges("/zz", new IZkChildListener() {
    @Override
    public void handleChildChange(String s, List<String> list) throws Exception {
        System.out.println(">>>进入了handleChildChange");
        System.out.println(">>>s = " + s);
        System.out.println(">>>list = " + list);
    }
});
// 注册一个监听事件,subscribeDataChanges 监听节点上数据的变化
zkClient.subscribeDataChanges("/zz", new IZkDataListener() {
    @Override
    public void handleDataChange(String dataPath, Object data) throws Exception {
        System.out.println(">>> 进入了handleDataChange");
        System.out.println(">>> dataPath = " + dataPath);
        System.out.println(">>> data = " + data);
    }
 
    @Override
    public void handleDataDeleted(String dataPath) throws Exception {
        System.out.println(">>> 进入了handleDataDeleted");
        System.out.println(">>> dataPath = " + dataPath);
    }
});
 
// 监听zookeeper状态变化
zkClient.subscribeStateChanges(new IZkStateListener() {
    @Override
    public void handleStateChanged(Watcher.Event.KeeperState state) throws Exception {
        System.out.println(">>> 进入了subscribeStateChanges");
        System.out.println(">>> state = " + state);
    }
 
    @Override
    public void handleNewSession() throws Exception {
        System.out.println(">>> 进入了handleNewSession");
    }
});

其他操作

  1. 返回PATH下的所有子节点:zkClient.getChildren(PATH);
  2. 写数据:zkClient.writeData(PATH, "456");
  3. 检查节点是否存在:zkClient.exists(PATH);