使用原生ZooKeeper客户端,比较的复杂,在调用APi时,需要传入较多的参数,并且不支持递归创建节点,递归删除节点,好在目前有很多优秀的框架对ZooKeeper进行了封装,ZkClient就是一款比较优秀的Zookeeper客户端。ZkClient相对于ZooKeeper API用起来更加简单。
Maven依赖引入
ZkClient是对ZooKeeper原生客户端的封装,除了因此ZooKeeper的jar包之外,我们还需要引入ZkClient的jar包,Maven如下:
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
ZkClient连接ZooKeeper
ZkClient是对ZooKeeper的封装,可以使用ZkClient连接Zookeeper,相对于原生ZooKeeper客户端,ZkClient新增了连接失败重试的机制。代码如下所示:
public static ZkClient getZkClient() {
if (zkClient == null) {
synchronized (ZkClientUtil.class) {
if (zkClient == null) {
//创建Zkclient实例,连接zookeeper
zkClient = new ZkClient(host, timeout);
}
}
}
return zkClient;
}
ZkClient CURD API
ZkClient对ZooKeeper原生增删改查API做了封装,使得对节点的增删改查变的更为简单。如下代码为ZkClient与原生API增删改查的比较。
public static void createNode() {
ZkClient zkClient = ZkClientUtil.getZkClient();
//相对于ZooKeeper原生APi,ZkClient提供了更为简单的API
//减少了参数的传入
//创建节点,自定义节点模式
zkClient.create("/test", "sssss", CreateMode.PERSISTENT);
//创建临时节点
zkClient.createEphemeral("/ephNode");
//创建临时有序节点
zkClient.createEphemeralSequential("/es","ss");
//创建持久节点
zkClient.createPersistent("/persistNode");
//创建持久有序节点
zkClient.createPersistentSequential("ps","ss");
}
public static void updateNode() {
ZkClient zkClient = ZkClientUtil.getZkClient();
//更改节点数据,不需要传入version,更为简单
zkClient.writeData("/test", "ssssssss");
}
public static void queryData() {
ZkClient zkClient = ZkClientUtil.getZkClient();
//读取节点数据
String test = zkClient.readData("/test");
//获取子节点
zkClient.getChildren("");
}
public static void deleteNode() {
ZkClient zkClient = ZkClientUtil.getZkClient();
//删除节点
zkClient.delete("/test");
//递归删除节点,原生API不支持递归删除
zkClient.deleteRecursive("/test");
}
ZkClient监听节点
ZkClient提供了subscribeChildChanges用于监听子节点的变化,提供了subscribeDataChanges用于监听节点数据的变化,它们的参数是类似,第一个参数为节点字符串,subscribeChildChanges的第二个参数为接口IZkChildListener实现,subscribeDataChanges的第二个参数为IZkDataListener接口实现,具体代码如下所示:
public static void listenerNode() throws IOException {
ZkClient zkClient = ZkClientUtil.getZkClient();
zkClient.subscribeChildChanges("/listener", new IZkChildListener() {
//监听子节点变化,父节点创建的时候 s为父节点 list为null
//子节点创建时 s为父节点,list为子节点,并且只能监听子节点变化,而不能监听孙子
//节点的变化
public void handleChildChange(String s, List<String> list) throws Exception {
}
});
//该方法只会监听当前节点数据的变化,如果其子节点数据变化,则不会被监听到
zkClient.subscribeDataChanges("/listener", new IZkDataListener() {
//节点数据变化的时候被调用,s为变化的节点,o为更新的数据
public void handleDataChange(String s, Object o) throws Exception {
}
//节点被删除的时候调用,s为被删除的节点
public void handleDataDeleted(String s) throws Exception {
}
});
}
使用ZkClient的监听器,我们不再像使用ZooKeeper原生APi那样,监听器是一次性的,每次在监听之前必须先获取节点数据。虽然ZkClient极大的改善了原生API的使用,但是用起来还有一些问题,比如在没有获取节点之前不能监听子节点下节点的数据变化,Curator客户端相对于ZkClient更加方便快捷。Curator会在下一章节讲解。