zookeeper学习记录-06 Zookeeper JavaAPI操作
来源:互联网 发布:mac下安装配置redis4 编辑:程序博客网 时间:2024/05/21 14:41
新建一个maven项目
引入依赖jar包
pom.xml引入依赖jar包,实际上还需要sla4j和log4j,但是maven会自动帮忙我们引入这里只需要引入Zookeeper的即可
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version></dependency>
新建一个类 - 测试连接Zookeeper服务器
import java.io.IOException;import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample implements Watcher{ private static CountDownLatch connCountDownLatch = new CountDownLatch(1); @Override public void process(WatchedEvent event) { System.out.println("Receive watched event : " + event); if(KeeperState.SyncConnected == event.getState()){ connCountDownLatch.countDown(); } } public static void main(String[] args) { try { ZooKeeper zooKeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample()); System.out.println(zooKeeper.getState()); connCountDownLatch.await(); System.out.println("Zookeeper session established"); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } }}
这里定义一个CountDownLatch ,在main方法中处于等待状态,当Zookeeper客户端连接上服务器之后解除阻塞,最终输出结果
CONNECTINGReceive watched event : WatchedEvent state:SyncConnected type:None path:nullZookeeper session established
Zookeeper构造说明:
在Zookeeper客户端与服务端建立连接是一个异步的过程,也就是说代码Zookeeper实例化之后马上返回,并没有真正的连接上了服务器端,所以代码中加上了CountDownLatch 来进行阻塞,当连接成功之后解除阻塞,打印最后一段话
创建节点
创建节点中两种方式,同步、异步.
参数说明:
同步
import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample_Create_API_Sync implements Watcher{ private static CountDownLatch connCountDownLatch = new CountDownLatch(1); @Override public void process(WatchedEvent event) { System.out.println("Receive watched event : " + event); if(KeeperState.SyncConnected == event.getState()){ connCountDownLatch.countDown(); } } public static void main(String[] args) throws Exception { ZooKeeper zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Create_API_Sync()); System.out.println(zookeeper.getState()); connCountDownLatch.await(); String path1 = zookeeper.create("/zk-test-PERSISTENT-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("Success create znode: " + path1); }}
输出结果如下:可以看到
CONNECTINGReceive watched event : WatchedEvent state:SyncConnected type:None path:nullSuccess create znode: /zk-test-PERSISTENT-
异步
异步方式于同步方式的区别在于节点的创建过程(包括网络通信和服务端的节点创建过程)是异步的,在同步接口调用过程中,开发者需要关注接口抛出异常的可能,但是在异步接口中,接口本身不会抛出异常,所有异常都会在回调函数中通过Result Code来体现。
import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.AsyncCallback;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample_Create_API_ASync implements Watcher{ private static CountDownLatch connCountDownLatch = new CountDownLatch(1); @Override public void process(WatchedEvent event) { System.out.println("Receive watched event : " + event); if(KeeperState.SyncConnected == event.getState()){ connCountDownLatch.countDown(); } } public static void main(String[] args) throws Exception { ZooKeeper zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Create_API_ASync()); System.out.println(zookeeper.getState()); connCountDownLatch.await(); zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, new IStringCallback(), "I am context. "); Thread.sleep(Integer.MAX_VALUE); } static class IStringCallback implements AsyncCallback.StringCallback{ @Override public void processResult(int rc, String path, Object ctx, String name) { System.out.println("Create path result: [" + rc + ", " + path + ", " + ctx + ", real path name: " + name); } }}
输出结果如下:
CONNECTINGReceive watched event : WatchedEvent state:SyncConnected type:None path:nullCreate path result: [-110, /zk-test-ephemeral-, I am context. , real path name: null
异步回调参数说明:
删除节点
删除节点提供了两个方法,分别是同步和异步.
参数说明:
同步
import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample_DELETE_API_Sync implements Watcher{ private static CountDownLatch connCountDownLatch = new CountDownLatch(1); @Override public void process(WatchedEvent event) { System.out.println("Receive watched event : " + event); if(KeeperState.SyncConnected == event.getState()){ connCountDownLatch.countDown(); } } public static void main(String[] args) throws Exception { ZooKeeper zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_DELETE_API_Sync()); System.out.println(zookeeper.getState()); connCountDownLatch.await(); zookeeper.delete("/zk-test-ephemeral-", 0); }}
异步
import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.AsyncCallback;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample_DELETE_API_ASync implements Watcher{ private static CountDownLatch connCountDownLatch = new CountDownLatch(1); @Override public void process(WatchedEvent event) { System.out.println("Receive watched event : " + event); if(KeeperState.SyncConnected == event.getState()){ connCountDownLatch.countDown(); } } public static void main(String[] args) throws Exception { ZooKeeper zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_DELETE_API_ASync()); System.out.println(zookeeper.getState()); connCountDownLatch.await(); zookeeper.create("/zk123", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zookeeper.delete("/zk123", 0 , new IVoidCallBack() , "test-delete async"); Thread.sleep(Integer.MAX_VALUE); } static class IVoidCallBack implements AsyncCallback.VoidCallback{ @Override public void processResult(int rc, String path, Object ctx) { System.out.println("rc : " + rc + " , path : " + path + " ctx : " + ctx.toString()); } }}
输出如下:
CONNECTINGReceive watched event : WatchedEvent state:SyncConnected type:None path:nullrc : 0 , path : /zk123 ctx : test-delete async
子节点读取
参数说明
同步
import java.util.List;import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.KeeperException;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.EventType;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample_Children_API_Sync implements Watcher{ private static CountDownLatch connCountDownLatch = new CountDownLatch(1); private static ZooKeeper zookeeper = null; private static String path = "/zk01"; @Override public void process(WatchedEvent event) { System.out.println("Receive watched event : " + event); if(KeeperState.SyncConnected == event.getState()){ if(event.getType() == EventType.None && null == event.getPath()){ connCountDownLatch.countDown(); }else if(event.getType() == EventType.NodeChildrenChanged){ try { System.out.println("child change reget childs : " + zookeeper.getChildren(path, true)); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Children_API_Sync()); System.out.println(zookeeper.getState()); connCountDownLatch.await(); zookeeper.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zookeeper.create(path + "/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); List<String> childs = zookeeper.getChildren(path, true); System.out.println(childs); zookeeper.create(path + "/c2", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); Thread.sleep(Integer.MAX_VALUE); }}
输出结果:
CONNECTINGReceive watched event : WatchedEvent state:SyncConnected type:None path:null[c1]Receive watched event : WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zk01child change reget childs : [c1, c2]
需要注意的是Watcher通知是一次性的,即一旦触发一次通知后,该Watcher就失效了,因此客户端需要反复注册Watcher,即程序中在process里面又注册了Watcher
异步
import java.util.List;import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.AsyncCallback;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.KeeperException;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.EventType;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;import org.apache.zookeeper.data.Stat;public class ZK_Sample_Children_API_ASync implements Watcher{ private static CountDownLatch connCountDownLatch = new CountDownLatch(1); private static ZooKeeper zookeeper = null; private static String path = "/zk02"; @Override public void process(WatchedEvent event) { System.out.println("Receive watched event : " + event); if(KeeperState.SyncConnected == event.getState()){ if(event.getType() == EventType.None && null == event.getPath()){ connCountDownLatch.countDown(); }else if(event.getType() == EventType.NodeChildrenChanged){ try { System.out.println("child change reget childs : " + zookeeper.getChildren(path, true)); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Children_API_ASync()); System.out.println(zookeeper.getState()); connCountDownLatch.await(); zookeeper.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zookeeper.create(path + "/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zookeeper.getChildren(path, true,new IChildren2Callback(),"获取子节点"); zookeeper.create(path + "/c2", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); Thread.sleep(Integer.MAX_VALUE); } static class IChildren2Callback implements AsyncCallback.Children2Callback { public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) { System.out.println("Get Children znode result: [response code: " + rc + ", path: " + path + ", ctx: " + ctx + ", children list: " + children + ", stat: " + stat); } }}
数据获取
Zookeeper API 提供了四个接口来获取数据,同样分同步,异步.
参数说明
更新数据
Zookeeper API 提供了两个接口来更新数据,同样分同步,异步.
参数说明
在更新数据时,setData方法存在一个version参数,其用于指定节点的数据版本,表明本次更新操作是针对指定的数据版本进行的,但是,在getData方法中,并没有提供根据指定数据版本来获取数据的接口,那么,这里为何要指定数据更新版本呢,这里方便理解,可以等效于CAS(compare and swap),对于值V,每次更新之前都会比较其值是否是预期值A,只有符合预期,才会将V原子化地更新到新值B。Zookeeper的setData接口中的version参数可以对应预期值,表明是针对哪个数据版本进行更新,假如一个客户端试图进行更新操作,它会携带上次获取到的version值进行更新,而如果这段时间内,Zookeeper服务器上该节点的数据已经被其他客户端更新,那么其数据版本也会相应更新,而客户端携带的version将无法匹配,无法更新成功,因此可以有效地避免分布式更新的并发问题。
检测节点是否存在
Zookeeper API 提供了四个接口来检测节点是否存在,同样分同步,异步.
参数说明
在调用接口时注册Watcher的话,还可以对节点是否存在进行监听,一旦节点被创建、被删除、数据更新,都会通知客户端
同步
import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.EventType;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample_Exist_API_Sync implements Watcher { private static CountDownLatch connectedSemaphore = new CountDownLatch(1); private static ZooKeeper zk; public static void main(String[] args) throws Exception { String path = "/zk-book"; zk = new ZooKeeper("192.168.7.151:2181", 5000, // new ZK_Sample_Exist_API_Sync()); connectedSemaphore.await(); zk.exists(path, true); zk.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.setData(path, "123".getBytes(), -1); zk.create(path + "/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("success create znode: " + path + "/c1"); zk.delete(path + "/c1", -1); zk.delete(path, -1); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { try { if (KeeperState.SyncConnected == event.getState()) { if (EventType.None == event.getType() && null == event.getPath()) { connectedSemaphore.countDown(); } else if (EventType.NodeCreated == event.getType()) { System.out.println("success create znode: " + event.getPath()); zk.exists(event.getPath(), true); } else if (EventType.NodeDeleted == event.getType()) { System.out.println("success delete znode: " + event.getPath()); zk.exists(event.getPath(), true); } else if (EventType.NodeDataChanged == event.getType()) { System.out.println("data changed of znode: " + event.getPath()); zk.exists(event.getPath(), true); } } } catch (Exception e) { } }}
输出结果
success create znode: /zk-bookdata changed of znode: /zk-booksuccess create znode: /zk-book/c1success delete znode: /zk-book
无论节点是否存在,都可以通过exists接口注册Watcher。
注册的Watcher,对节点创建、删除、数据更新事件进行监听。
对于指定节点的子节点的各种变化,不会通知客户端。
异步
import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.AsyncCallback;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.EventType;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;import org.apache.zookeeper.data.Stat;public class ZK_Sample_Exist_API_ASync implements Watcher { private static CountDownLatch connectedSemaphore = new CountDownLatch(1); private static ZooKeeper zk; public static void main(String[] args) throws Exception { String path = "/zk-book"; zk = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Exist_API_ASync()); connectedSemaphore.await(); zk.exists(path, true, new IIStatCallback(), null); zk.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.setData(path, "123".getBytes(), -1); zk.create(path + "/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("success create znode: " + path + "/c1"); zk.delete(path + "/c1", -1); zk.delete(path, -1); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { try { if (KeeperState.SyncConnected == event.getState()) { if (EventType.None == event.getType() && null == event.getPath()) { connectedSemaphore.countDown(); } else if (EventType.NodeCreated == event.getType()) { System.out.println("success create znode: " + event.getPath()); zk.exists(event.getPath(), true, new IIStatCallback(), null); } else if (EventType.NodeDeleted == event.getType()) { System.out.println("success delete znode: " + event.getPath()); zk.exists(event.getPath(), true, new IIStatCallback(), null); } else if (EventType.NodeDataChanged == event.getType()) { System.out.println("data changed of znode: " + event.getPath()); zk.exists(event.getPath(), true, new IIStatCallback(), null); } } } catch (Exception e) { } } static class IIStatCallback implements AsyncCallback.StatCallback { public void processResult(int rc, String path, Object ctx, Stat stat) { System.out.println("rc: " + rc + ", path: " + path + ", stat: " + stat); } }}
输出结果
rc: -101, path: /zk-book, stat: nullsuccess create znode: /zk-bookrc: 0, path: /zk-book, stat: 12884901993,12884901993,1508491896292,1508491896292,0,0,0,0,0,0,12884901993data changed of znode: /zk-bookrc: 0, path: /zk-book, stat: 12884901993,12884901994,1508491896292,1508491896313,1,0,0,0,3,0,12884901993success create znode: /zk-book/c1success delete znode: /zk-bookrc: -101, path: /zk-book, stat: null
当节点不存在时,其rc(ResultCode)为-101。
权限认证
在实际过程中,可能是一个Zookeeper集群,有多个项目,多个服务共同使用,避免错误操作,数据读取权限,就需要进行认证了。
Zookeeper api 提供了权限认证
参数说明:
认证失败示例
import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample_ACL_API_AUTH_FAIL{ public static void main(String[] args) throws Exception { String path = "/zk-book"; ZooKeeper zookeeper1 = new ZooKeeper("192.168.7.151:2181", 5000, null); zookeeper1.addAuthInfo("digest", "foo:true".getBytes()); zookeeper1.create(path, "init".getBytes(), Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL); System.out.println("success create znode: " + path); ZooKeeper zookeeper2 = new ZooKeeper("192.168.7.151:2181", 5000, null); zookeeper2.getData(path, false, null); }}
输出结果
success create znode: /zk-bookException in thread "main" org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /zk-book at org.apache.zookeeper.KeeperException.create(KeeperException.java:113) at org.apache.zookeeper.KeeperException.create(KeeperException.java:51) at org.apache.zookeeper.ZooKeeper.getData(ZooKeeper.java:1155) at org.apache.zookeeper.ZooKeeper.getData(ZooKeeper.java:1184) at com.jx.zk.first.ZK_Sample_ACL_API_AUTH_FAIL.main(ZK_Sample_ACL_API_AUTH_FAIL.java:16)
认证通过
import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class ZK_Sample_ACL_API_AUTH_SUCC{ public static void main(String[] args) throws Exception { String path = "/zk-book"; ZooKeeper zookeeper1 = new ZooKeeper("192.168.7.151:2181", 5000, null); zookeeper1.addAuthInfo("digest", "foo:true".getBytes()); zookeeper1.create(path, "init".getBytes(), Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL); System.out.println("success create znode: " + path); ZooKeeper zookeeper2 = new ZooKeeper("192.168.7.151:2181", 5000, null); zookeeper2.addAuthInfo("digest", "foo:true".getBytes()); byte[] bt = zookeeper2.getData(path, false, null); System.out.println(new String(bt)); }}
输出结果
success create znode: /zk-bookinit
不同的客户端之间带上一样的认证信息即可.
- zookeeper学习记录-06 Zookeeper JavaAPI操作
- zookeeper JavaAPI入门操作
- zookeeper学习记录-05 Zookeeper命令行操作
- zookeeper javaAPI
- zookeeper-05-javaAPI使用
- ZooKeeper级联删除javaAPI
- Zookeeper中javaAPI初试
- zookeeper javaApi/zkclient
- zookeeper学习记录
- zookeeper学习记录
- zookeeper学习记录
- zookeeper学习记录
- zookeeper学习记录
- zookeeper学习记录
- zookeeper学习记录
- zookeeper学习记录
- zookeeper 学习记录1
- zookeeper 学习记录2
- [微信小程序]省市区地区选择器(完整代码赋效果图)
- javascript判断是否是QQ或微信手机内置浏览器
- iOS/Android 微信及浏览器中唤起本地APP
- SpringMVC工作原理
- 深入理解Ribbon之源码解析
- zookeeper学习记录-06 Zookeeper JavaAPI操作
- Deep Learning:深度前馈神经网络(五)
- 一周五次课(10月20日)
- tornado学习之路
- 自定义View笔记(三) --- ViewDragHelper
- 演示文件IO的例子
- Linux终端部分快捷方式
- C++ 遗传学SFLA混合蛙跳算法
- PopupWindow在7.0上显示的坑