Zookeeper--开源客户端ZkClient常用API

ZkClient

ZkClient是Github上一个开源的ZooKeeper 客户端,是由Datameer 的工程师StefanGroschupf和Peter Voss 一起开发的。ZkClient在ZooKeeper原生API接口之上进行了包装,是一个更易用的ZooKeeper客户端。同时,ZkClient在内部实现了诸如Session 超时重连、Watcher 反复注册等功能,使得ZooKeeper客户端的这些繁琐的细节工作对开发人员透明。

Maven依赖:

<dependencies>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
    </dependencies>
创建会话

ZkClient中,有如下7种构造方法:

  1. public ZkClient(String serverstring)
  2. public ZkClient(String zkServers, int connectionTimeout)
  3. public ZkClient(String zkServers, int sessionTimeout, int connectionTimeout)
  4. public ZkClient(String zkServers, int sessionTimeout, int connectionTimeout, ZkSerializer zkSerializer)
  5. public ZkClient(IZkConnection connection)
  6. public ZkClient(IZkConnection connection, int connectionTimeout)
  7. public ZkClient(IZkconnection zkConnection, int connectionTImeout, ZkSerializer zkSerializer)

构造方法参数说明:
在这里插入图片描述
Zookeeper的原生JavaAPI中创建会话是一个异步过程,但经过ZkClient包装后,这个异步过程被同步化了。

org. IOItec. zkclient . IZkConnection接口是对ZooKeeper原生接口最直接的包装,也是和ZooKeeper最直接的交互层,里面包含了添、删、改、查等一系列接口的定义。ZkClient 默认提供对IZkConnection接口的两种实现,分别是ZkConnection和InMemoryConnection,前者是我们最常用的实现方式。通常开发人员不需要对IZkConnection 进行改造,直接使用ZkConnection这个实现就可以完成绝大部分的业务需求。

ZkClient和ZooKeeper原生构造方法的最大区别,那就是在ZkClient的构造方法中,不再提供传入Watcher对象的参数了。ZkClient 引入了大多数Java 程序都使用过的Listener 来实现Watcher注册。值得一提的是,ZkClient 从API级别来支持Watcher 监听的注册,这样的用法更贴近Java工程师的开发习惯。

public class Create_Session_Sample {
    public static void main(String[] args) {
        ZkClient zkClient = new ZkClient("127.0.0.1:2181", 5000);
        System.out.println("ZooKeeper session established.");
    }
}

输出:

ZooKeeper session established.
创建结点

ZkClient中提供了以下- -系列接口来创建节点,开发者可以通过这些接口来进行各种类型的节点创建:

  1. String create(final String path, Object data, final CreateMode mode)
  2. String create(final String path, Object data, final List<ACL> acl, final CreateMode mode)
  3. void create(final String path, Object data, final CreateMode mode, final AsyncCallback.StringCallback callback, final Object context)
  4. void createEphemeral(final String path)
  5. void createEphemeral(final String path, final Object data)
  6. void createPersistent(String path)
  7. void createPersistent(String path, boolean createParents)
  8. void createPersistent(String path, Object data)
  9. void createPersistent(String path, List<ACL> acl, Object data)
  10. String createPersistenSequential(String path, Object data)
  11. String createEphemeralSequential(final String path, final Object data)

在这里插入图片描述

ZkClient提供了较多的创建节点API接口,其中前面三个接口和ZooKeeper原生的创建节点API接口基本一致,唯一不同的地方在于,原生接口只允许传入byte[ ]类型的参数,而ZkClient提供的接口,由于支持了自定义序列化器,因此可以传入复杂对象作为参数。

再来看后面的几个接口,从接口的名字上就可以看出这些接口将节点的创建类型隐藏在了方法名中,如createEphemeral接口是创建临时节点,而createPersistentSequential接口则是创建持久顺序结点。

public class Create_Session_Sample {
    public static void main(String[] args) {
        ZkClient zkClient = new ZkClient("127.0.0.1:2181", 5000);
        System.out.println("ZooKeeper session established.");

        String path = "/zk-test/c1";
        //递归创建父节点
        zkClient.createPersistent(path, true);
    }
}

在这里插入图片描述

删除结点

在ZkClient中,可以通过以下API来删除指定结点:

  1. boolean delete(final String path)
  2. delete(final String path, final AsyncCallback.VoidCallback callback, final Object context)
  3. boolean deleteRecursive(String path)

在这里插入图片描述

在Zookeeper中,只允许删除叶子结点,但是通过deleteRecursive这个接口,可以帮助自动帮我们完成逐层遍历删除结点的工作。

zkClient.deleteRecursive("/zk-test");

在这里插入图片描述

读取数据

获取结点的子节点列表:getChildren

List<String> getChildren(String path)

ZkClient只提供了一个对外API,用于获取指定节点的子节点列表。这个API的返回值是子节点的相对路径。

例如,ZooKeeper 服务器上存在/zk book/c1和/zk-book/c2 这样两个节点,那么调用该API获取/zk-book的子节点列表,返回值是[cl, c2]。

List<String> children = zkClient.getChildren("/zk-test");
        children.stream().forEach(e -> {
            System.out.println(e);
        });
c1
c2

和ZooKeeper原生API 相比,ZkClient 提供的API没有了Watcher注册的功能。客户端可以通过注册相关的事件监听来实现对ZooKeeper服务端事件的订阅。在获取子节点列表这个接口上,可以通过如下API来进行注册监听:
List<String> subscribeChildChanges(String path, IZkChildListener listener)

通过该API的调用,就完成了事件监听的注册。从API方法中,可以看出,注册的是对子节点列表变更的监听,也就是说,一旦子节点列表发生变更,ZooKeeper 服务端就会向客户端发出事件通知,由这个Listener 来处理。下面给出这个Listener 接口的定义:

public interface IZkChildListener {
    void handleChildChange(String var1, List<String> var2) throws Exception;
}

handleChildChange方法参数说明:
在这里插入图片描述

IZkChildListener监听的事件类型:
在这里插入图片描述

public class Get_Children_Sample {
    public static void main(String[] args) throws InterruptedException {
        String path = "/zk-book";
        ZkClient zkClient = new ZkClient("127.0.0.1:2181", 5000);

        zkClient.subscribeChildChanges(path, new IZkChildListener() {
            @Override
            public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
                System.out.println(parentPath + " 's child changed, currentChilds:" + currentChilds);
            }
        });
        zkClient.createPersistent(path);
        Thread.sleep(1000);
        System.out.println(zkClient.getChildren(path));
        Thread.sleep(1000);
        zkClient.createPersistent(path + "/c1");
        Thread.sleep(1000);
        zkClient.delete(path + "/c1");
        Thread.sleep(1000);
        zkClient.delete(path);
        Thread.sleep(Integer.MAX_VALUE);

    }
/zk-book 's child changed, currentChilds:[]
[]
/zk-book 's child changed, currentChilds:[c1]
/zk-book 's child changed, currentChilds:[]
/zk-book 's child changed, currentChilds:null

在上面这个示例程序中,首先对/zk-book注册了IZkChildListener监听,此时该节点并不存在。当创建了/zk-book节点后,客户端立即会收到来自服务端的事件通知,当然此时接收到的子节点列表为null。然后继续创建节点/zk-book/cI,此时客户端就会收到子节点列表变更通知,同时收到最新的子节点列表为[cI]。随后,我们删除了/zk-book/cl节点,客户端同样会收到事件变更通知。最后,当将/zk-book 节点本身删除的时候,客户端收到了事件通知,同时可以发现,此时子节点列表为null。

从上面的示例程序和输出结果中,我们可以得出以下3个结论。

  1. 客户端可以对一个不存在的节点进行子节点变更的监听。
  2. 一旦客户端对-一个节点注册了子节点列表变更监听之后,那么当该节点的子节点列表发生变更的时候,服务端都会通知客户端,并将最新的子节点列表发送给客户端。3. 该节点本身的创建或删除也会通知到客户端。
    另外,还需要明确的一点是,和ZooKeeper原生提供的Watcher不同的是,ZkClient 的Listener不是一次性的,客户端只要注册一次就一直生效。

获取数据:getData
在ZkClient中,可以通过以下API来获取指定结点的数据内容:

  1. <T extends Object> T readData(String path)
  2. <T extends Object> T readData(String path, boolean returnNullIfPathNotExists)
  3. <T extends Object> T readData(String path, Stat stat)

在这里插入图片描述

通过调用这个接口,就可以获取指定节点的数据内容。注意,方法的返回值,在ZkClient内部已经被反序列化成指定对象。

另外,该接口对服务端事件的监听,同样是通过注册指定的Listener来实现的:

public interface IZkDataListener {
    void handleDataChange(String var1, Object var2) throws Exception;

    void handleDataDeleted(String var1) throws Exception;
}

参数说明:
在这里插入图片描述
事件说明:
在这里插入图片描述

public class Get_Data_Sample {
    public static void main(String[] args) throws InterruptedException {
        String path = "/zk-book";
        ZkClient zkClient = new ZkClient("127.0.0.1:2181", 5000);

        zkClient.createEphemeral(path, "123");
        //注册监听器
        zkClient.subscribeDataChanges(path, new IZkDataListener() {
            @Override
            public void handleDataChange(String dataPath, Object data) throws Exception {
                System.out.println("Node " + dataPath + "changed, new data:" + data);
            }

            @Override
            public void handleDataDeleted(String dataPath) throws Exception {
                System.out.println("Node " + dataPath + "deleted.");
            }
        });

        System.out.println((String) zkClient.readData(path));
        zkClient.writeData(path, "456");
        Thread.sleep(1000);
        zkClient.delete(path);
        Thread.sleep(Integer.MAX_VALUE);
    }
}
123
Node /zk-bookchanged, new data:456
Node /zk-bookdeleted.

首先创建了结点/zk-book,并且调用readData接口来获取其数据内容,同时在该节点上注册了IZkDataListener监听,实现对该节点数据变更的监听。这样一来,之后凡是该节点数据变化或是该节点被删除,服务端都会向客户端发出事件通知。

更新数据

在ZkClient中,可以通过以下API来更新指定结点的数据:

  1. void writeData(String path, Object data)
  2. void writeData(final String path, Object data, final int expectedVersion)

在这里插入图片描述

检测结点是否存在

在ZkClient中,可以通过以下API来检测指定结点是否存在:

boolean exists(final String path)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值