Zookeeper客户端(三)—— ZkClient

Zookeeper客户端(一)—— 原生客户端中,我们使用了原生的客户端对Zookeeper节点进行操作。但是在使用的过程中,我们发现了一些弊端,比如原生客户端的会话连接是异步的,所以我们就必须在在代码中进行相应的处理,比如使用CountDownLatch和Watch机制来判断是否成功连接;另外还有一点就是Watch需要重复注册,这一点我们在代码中也进行演示了。


基于以上存在的弊端,所以就还有一些其他的客户端,如ZkClient,zkClient是一个开源的zk客户端,其在原生API基础上封装,是一个更易于使用的Zookeeper客户端。


首先我们在使用ZkClient的时候,我们除了引入Zookeeper的依赖外,还需要引入ZkClient依赖,如下:

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

引入相关依赖后,我们就可以使用下列代码来连接Zookeeper了,是不是发现比我们之前使用原生客户端要来的简单很多,就不需要我们自己来控制了。

public class ZkClientTest {

    public static final String CONNECT_ADDR = "192.168.80.130:2181";

    public static void main(String[] args) {
        ZkClient zkClient = new ZkClient(CONNECT_ADDR, 5000);
    }
}



除了上述的便利,ZkClient还有什么好处呢?比如在原生客户端中,我们介绍了对节点的创建、删除等操作,但是我们发现在介绍创建节点和删除节点的时候,就没有介绍如何能够一次性的建立多个节点,或者一次性删除包括子节点的节点,及rmr方法的实现。


因为在原生的客户端中就不执行这种操作,那么ZkClient支持么?是的,那么如何操作呢,如下:
在这里插入图片描述


除了我们连接非常的简单,以及上述为我们提供的可以递归创建节点和递归删除节点的方法外,ZkClinet在很多其它的方法上也为我们简便了用法,如我们在原生客户端中,如果获取一个不存在的节点,肯定就直接报错了,如下:
在这里插入图片描述
在这里插入图片描述

但是原生客户端也是为我们提供的方法的,如下,我们可以在获取节点前,先判断该节点是否存在,如下:
在这里插入图片描述
在这里插入图片描述


在ZkClient中就没有这么麻烦了,它允许我们直接获取该节点,我们只需加上允许为空即可
在这里插入图片描述
在这里插入图片描述



其余的ZkClient操作节点其实和原生的客户端用户基本类似,如获取节点数据,修改节点数据,获取节点下子节点等等。
在这里插入图片描述


这里有一点我们需要注意的是,可能我们在读取节点会抛出异常,比如这里我们手动在服务器上生成一个 /node2 节点,然后我们使用ZkClient进行读取,结果如下:
在这里插入图片描述
在这里插入图片描述

导致该问题,一般都是因为序列化问题,这里我们可以自己实现一个ZK的序列化

public class MyZkSerializer implements ZkSerializer {
    /**
     * 序列化,将对象转化为字节数组
     */
    @Override
    public byte[] serialize(Object o) throws ZkMarshallingError {
        return String.valueOf(o).getBytes(Charsets.UTF_8);
    }

    /**
     * 反序列化,将字节数组转化为UTF-8字符串
     */
    @Override
    public Object deserialize(byte[] bytes) throws ZkMarshallingError {
        return new String(bytes, Charsets.UTF_8);
    }
}

在这里插入图片描述




最后我们再来看一看Watch在ZkClient中的用法,在原生客户端中Watch的用法时非常麻烦的,它只会生成一次,我们每次使用都必须进行注册,那么ZkClient中是如何使用的呢?在ZkClient中为我们提供了一个比较好用的Listener,其用法如下:
在这里插入图片描述

上述我们在做出节点变化时,使其形成休眠了2秒,这里是为了可以让Listener有充分的时间来打印出信息,如果我们不让线程修改,可能程序就直接结束了
在这里插入图片描述

另外我们在writeDatadelete节点操作中间,也是休眠了2秒,否则会和我们预期的不一致,大家可以尝试一下,结果如下:
在这里插入图片描述
在这里插入图片描述



上述我们介绍的监听节点数据的变化,这里我们还可以监听节点的变化,如下:
在这里插入图片描述
在这里插入图片描述

这里我们在进行节点的操作时,同样我们进行了线程休眠,我们在两次添加节点的中间也是添加了线程休眠,否则的话,可能第一次修改就不会被感知到,最后只会打印出最后一次的变化,即 [n1, n2]


另外我们在 /node1 节点上注册了节点变化监听,所以 /node1 节点下有子节点的添加、删除操作都会被感知到,但是 /node1 节点下子节点的子节点我们就不会进行监听了,删除也是同样的
在这里插入图片描述
在这里插入图片描述

从控制台中就可以发现,/node1 子节点添加了子节点,是不会触发该事件的,删除同理,可自行测试。

另外我们除了可以监听节点数据,子节点变化,还可以监听连接的状态(就是原生客户端监听用于连接)等等,这些就不一一介绍了
在这里插入图片描述

发布了286 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/newbie0107/article/details/104891036
今日推荐