版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yhl_jxy/article/details/90315575
前言
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); } }
监听处理注册后,节点发生改变,触发相应的事件。
文章来源: https://blog.csdn.net/yhl_jxy/article/details/90315575