使用Java操作Zookeeper
目录
一、介绍
2.1、导入依赖
2.2、连接zk集群
2.3、操作数据操作
3.1、导入依赖
3.2、使用示例
一、介绍
这里主要记录通过Java调用API来操作Zookeeper集群的数据,对于zookeeper集群的搭建或者命令,可以参考:
目前接触到的Java操作Zookeeper,有两套API,一套是zookeeper官方提供的(zookeeper),另外一套是封装了官方API的API(zkClient),从描述上来看,就知道,官方的API可能不是那么好用,不然也不会在封装。
二、zookeeper API
2.1、导入依赖
使用zookeeper官方api的时候,请保证jar包的版本,和zk集群中zk的版本相同
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.7</version> </dependency>
2.2、连接zk集群
下面是代码示例,两种形式(分别使用匿名类和Lambda表达式):
package cn.ganlixin.zk; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import org.junit.Test; import java.io.IOException; public class ZookeeperDemo { @Test public void connectZkCluster() throws IOException, KeeperException, InterruptedException { // 构造方法 // ZooKeeper(String connectString, int sessionTimeout, Watcher watcher) // 匿名对象形式 ZooKeeper zooKeeper = new ZooKeeper( "192.168.1.3:2181,192.168.1.4:2181,192.168.1.5:2181", 20000, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { // 发生变更的节点路径 String path = watchedEvent.getPath(); System.out.println("path:" + path); // 通知状态 Watcher.Event.KeeperState state = watchedEvent.getState(); System.out.println("KeeperState:" + state); // 事件类型 Watcher.Event.EventType type = watchedEvent.getType(); System.out.println("EventType:" + type); } } ); // 关闭连接 zooKeeper.close(); // Lamdba形式 ZooKeeper zk = new ZooKeeper( "192.168.1.3:2181,192.168.1.4:2181,192.168.1.5:2181", 20000, watchedEvent -> { // 发生变更的节点路径 String path = watchedEvent.getPath(); System.out.println("path:" + path); // 通知状态 Watcher.Event.KeeperState state = watchedEvent.getState(); System.out.println("KeeperState:" + state); // 事件类型 Watcher.Event.EventType type = watchedEvent.getType(); System.out.println("EventType:" + type); } ); zk.close(); } }
运行上面的代码,控制台输出如下(输出了两遍,是因为创建了两次连接)
path:null KeeperState:SyncConnected EventType:None path:null KeeperState:SyncConnected EventType:None
2.3、操作数据操作
操作Zk中的数据,方式也很简单,只需要使用创建的zk连接,调用对应的方法即可(方法名与zk命令行中命令相同)
package cn.ganlixin.zk; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; import org.junit.Test; import java.io.IOException; public class ZookeeperDemo { @Test public void manageData() throws KeeperException, InterruptedException, IOException { // 创建zk连接 ZooKeeper zk = new ZooKeeper( "192.168.1.3:2181,192.168.1.4:2181,192.168.1.5:2181", 20000, null ); // 创建节点 zk.create("/abc", "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); // 获取节点数据 // getData(String path, boolean watch, Stat stat); Stat stat = new Stat(); byte[] data = zk.getData("/abc", false, stat); System.out.println(new String(data)); // 数据内容 123 System.out.println(stat.getDataLength()); // 节点状态(数据长度) 3 // 对/abc进行watch zk.getData("/abc", watchedEvent -> { System.out.println("path:" + watchedEvent.getPath()); System.out.println("KeeperState:" + watchedEvent.getState()); System.out.println("EventType:" + watchedEvent.getType()); }, null); // 设置节点数据 // setData(String path, byte[] data, int version) // 指定version为-1,表示不关心版本 zk.setData("/abc", "456".getBytes(), -1); // 设置两次,第二次不会触发通知 zk.setData("/abc", "789".getBytes(), -1); // 阻塞,以等待通知 Thread.sleep(1000); zk.close(); } }
上面的程序,运行输出结果如下:
123 3 path:/abc KeeperState:SyncConnected EventType:NodeDataChanged
可以看到,只显示了一次通知,和与预期相符。
三、zkClient API
因为Zookeeper API比较复杂,使用并不方便,所以出现了ZkClient,ZkClient对Zookeeper API进行了封装,利用ZkClient可以更加方便地对Zookeeper进行操作。
3.1、导入依赖
因为zkClient是对zookeeper的再封装,所以需要注意zkClient中zookeeper的版本与zk集群的版本相同,可以在maven仓库中查看对应关系
<!-- https://mvnrepository.com/artifact/com.101tec/zkclient --> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency>
3.2、使用示例
下面是个简单的示例:
package cn.ganlixin.zk; import org.I0Itec.zkclient.IZkChildListener; import org.I0Itec.zkclient.IZkStateListener; import org.I0Itec.zkclient.ZkClient; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.Watcher; import org.junit.Test; import java.util.List; public class ZkClientDemo { @Test public void testConn() throws InterruptedException { ZkClient zkClient = new ZkClient( "192.168.1.3:2181,192.168.1.4:2181,192.168.1.5:2181", 20000 ); // 创建节点 zkClient.createPersistent("/abc", "hello"); zkClient.createEphemeral("/xyz", "world"); zkClient.create("/opq", "world", CreateMode.EPHEMERAL_SEQUENTIAL); String data = zkClient.readData("/abc"); System.out.println(data); // 监听状态变化 zkClient.subscribeStateChanges(new IZkStateListener() { @Override public void handleStateChanged(Watcher.Event.KeeperState keeperState) throws Exception { System.out.println("state:" + keeperState); } @Override public void handleNewSession() throws Exception { System.out.println("new session"); } @Override public void handleSessionEstablishmentError(Throwable throwable) throws Exception { throwable.printStackTrace(); } }); // 监听子节点发生变化 zkClient.subscribeChildChanges("/", new IZkChildListener() { @Override public void handleChildChange(String path, List<String> list) throws Exception { System.out.println("watch path:" + path); // 输出所有子节点 list.forEach(str -> { System.out.println(str); }); } }); Thread.sleep(100000); } }
如需转载,请注明文章出处,谢谢!!!