Zookeeper JAVA API的使用
0. 前言
zookeeper安装及使用 http://www.cnblogs.com/rocky-fang/p/7880309.html
1. 开发环境配置
1.1 idea创建一个maven工程
1.2 pom配置jar
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.rocky.learn</groupId> <artifactId>zk</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.1</version> </dependency> </dependencies> </project>
2. API使用
2.1 连接Zookeep Server
code
import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/12. */ public class ZookeeperTestConnection implements Watcher { private static CountDownLatch countDownLatch = new CountDownLatch(1); public void process(WatchedEvent event) { System.out.println("receive the event:"+event); if(Event.KeeperState.SyncConnected == event.getState()) countDownLatch.countDown(); } public static final String ADDRESS = "192.168.1.8:2181"; public static void main(String[] args) throws IOException { ZooKeeper zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestConnection()); System.out.println(zooKeeper.getState()); try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("zookeeper session established"); } }
控制台
2.2 创建节点
2.2.1 同步创建
code
import org.apache.zookeeper.*; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/12. */ public class ZookeeperTestCreateNodeSync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "192.168.1.8:2181"; private static final String PREFIX = "/mytest-sync-create-"; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { ZooKeeper zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestCreateNodeSync()); System.out.println("state:"+zooKeeper.getState()); countDownLatch.await(); String path1 = zooKeeper.create(PREFIX, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println("success create znode:"+ path1); String path2 = zooKeeper.create(PREFIX, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); System.out.println("success create znode:"+ path2); zooKeeper.close(); } public void process(WatchedEvent event) { //连上了 if(Event.KeeperState.SyncConnected == event.getState()) countDownLatch.countDown(); } }
控制台
2.2.2 异步创建
import org.apache.zookeeper.*; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/12. */ public class ZookeeperTestCreateNodeAsync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "192.168.1.8:2181"; private static final String PREFIX_ASYNC = "/mytest-async-create-"; public static void main(String[] args) throws IOException, InterruptedException { ZooKeeper zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestCreateNodeAsync()); System.out.println("state:"+zooKeeper.getState()); countDownLatch.await(); zooKeeper.create(PREFIX_ASYNC, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, new IStringCallBack(), "my test text...1"); zooKeeper.create(PREFIX_ASYNC, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, new IStringCallBack(), "my test text...2"); zooKeeper.create(PREFIX_ASYNC, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL, new IStringCallBack(), "my test text...3"); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()) countDownLatch.countDown(); } } class IStringCallBack implements AsyncCallback.StringCallback { public void processResult(int rc, String path, Object ctx, String name) { System.out.println("rc:"+rc+",path:"+path+",ctx:"+ctx+"name,"+name); } }
控制台
说明:同步需要关注接口异常,异步接口不会反回异常,而是在回调函数中通过result code体现
2.3 创建节点
只允许删除叶子节点,即如果节点包含子节点,则必须先删除子节点才能删除本节点。
2.3.1 同步方式
import org.apache.zookeeper.*; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/12. */ public class ZookeeperTestDeleteNodeSync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "192.168.1.8:2181"; private static final String PREFIX_SYNC = "/mytest-sync-delete-"; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { ZooKeeper zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestDeleteNodeSync()); countDownLatch.await(); zooKeeper.create(PREFIX_SYNC, "mydelete".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zooKeeper.create(PREFIX_SYNC + "/c1", "mydelete".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); try { zooKeeper.delete(PREFIX_SYNC, -1); } catch (Exception e) { System.out.println("faile to delete path:"+PREFIX_SYNC); } zooKeeper.delete(PREFIX_SYNC + "/c1", -1); System.out.println("success to delete /c1"); zooKeeper.delete(PREFIX_SYNC , -1); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()) countDownLatch.countDown(); } } }
控制台
2.3.2 异步方式
import org.apache.zookeeper.*; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/12. */ public class ZookeeperTestDeleteNodeASync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "192.168.1.8:2181"; private static final String PREFIX_SYNC = "/mytest-async-delete-"; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { ZooKeeper zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestDeleteNodeASync()); countDownLatch.await(); zooKeeper.create(PREFIX_SYNC, "mydelete".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zooKeeper.create(PREFIX_SYNC + "/c1", "mydelete".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zooKeeper.delete(PREFIX_SYNC , -1, new IVoidCallback(), null); zooKeeper.delete(PREFIX_SYNC + "/c1", -1, new IVoidCallback(), null); zooKeeper.delete(PREFIX_SYNC , -1, new IVoidCallback(), null); System.out.println("success to delete /c1"); zooKeeper.delete(PREFIX_SYNC , -1); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()) countDownLatch.countDown(); } } } class IVoidCallback implements AsyncCallback.VoidCallback { public void processResult(int rc, String path, Object ctx) { System.out.println(rc + "::" + path + "::" +ctx); } }
控制台
2.4 获取子节点
2.4.1 同步方式
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Id; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestGetChildrenNodeSync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "192.168.1.8:2181"; private static final String PREFIX_SYNC = "/mytest-sync-getChild-"; private static ZooKeeper zooKeeper ; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestGetChildrenNodeSync()); countDownLatch.await(); zooKeeper.create(PREFIX_SYNC, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zooKeeper.create(PREFIX_SYNC + "/c1", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println(zooKeeper.getChildren(PREFIX_SYNC, true)); zooKeeper.create(PREFIX_SYNC + "/c2", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println(zooKeeper.getChildren(PREFIX_SYNC, true)); Thread.sleep(1000); zooKeeper.create(PREFIX_SYNC + "/c3", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println(zooKeeper.getChildren(PREFIX_SYNC, true)); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); }else if(Event.EventType.NodeChildrenChanged == event.getType()){ try { System.out.println("get Child:" + zooKeeper.getChildren(event.getPath(), true)); } catch (Exception e) { e.printStackTrace(); } } } } }
控制台
Watcher通知是一次性的,即一旦触发一次通知后,该Watcher就失效了,因此客户端需要反复注册Watcher,即程序中在process里面又注册了Watcher,zooKeeper.getData(path,watch,stat), 第二个参数值设为true则添加一次监听, 否则,将无法获取c3节点的创建而导致子节点变化的事件。
2.4.2 异步方式
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.List; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestGetChildrenNodeASync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "192.168.1.8:2181"; private static final String PREFIX_SYNC = "/mytest-async-getChild-"; private static ZooKeeper zooKeeper ; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestGetChildrenNodeASync()); countDownLatch.await(); zooKeeper.create(PREFIX_SYNC, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zooKeeper.create(PREFIX_SYNC + "/c1", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); zooKeeper.getChildren(PREFIX_SYNC, true, new IChildren2Callback(), null); zooKeeper.create(PREFIX_SYNC + "/c2", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); zooKeeper.getChildren(PREFIX_SYNC, true, new IChildren2Callback(), null); Thread.sleep(1000); zooKeeper.create(PREFIX_SYNC + "/c3", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); zooKeeper.getChildren(PREFIX_SYNC, true, new IChildren2Callback(), null); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); }else if(Event.EventType.NodeChildrenChanged == event.getType()){ try { System.out.println("get Child:" + zooKeeper.getChildren(event.getPath(), true)); } catch (Exception e) { e.printStackTrace(); } } } } } class IChildren2Callback implements AsyncCallback.Children2Callback { public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) { System.out.println(rc + "::" + path + "::" +ctx +"::" + children + "::" + stat); } }
控制台
2.5 节点的数据获取
2.5.1 同步方式
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestGetNodeDataSync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "10.0.40.10:2181"; private static final String PREFIX_SYNC = "/mytest-sync-getData4-"; private static ZooKeeper zooKeeper ; private static final Stat stat = new Stat(); public static void main(String[] args) throws IOException, InterruptedException, KeeperException { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestGetNodeDataSync()); countDownLatch.await(); zooKeeper.create(PREFIX_SYNC, "hellodata".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println("the data of node:" + new String(zooKeeper.getData(PREFIX_SYNC, true, stat))); System.out.println("czxid::"+stat.getCzxid()+",mzxid::" + stat.getMzxid() + ",version::" + stat.getVersion()); zooKeeper.setData(PREFIX_SYNC, "hello2data".getBytes(), -1); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); }else if(Event.EventType.NodeDataChanged == event.getType()){ try { System.out.println("the data of:" + event.getPath() + " is::" + new String(zooKeeper.getData(event.getPath(), true, stat))); System.out.println("watch czxid::"+stat.getCzxid()+",mzxid::" + stat.getMzxid() + ",version::" + stat.getVersion()); } catch (Exception e) { e.printStackTrace(); } } } } }
控制台
2.5.2 异步方式
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestGetNodeDataASync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "10.0.40.10:2181"; private static final String PREFIX_SYNC = "/mytest-async-getData8-"; private static ZooKeeper zooKeeper ; private static final Stat stat = new Stat(); public static void main(String[] args) throws IOException, InterruptedException, KeeperException { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestGetNodeDataASync()); countDownLatch.await(); zooKeeper.create(PREFIX_SYNC, "hello7data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zooKeeper.getData(PREFIX_SYNC, true, new IDataCallback(), null); for(int i=0; i<3; i++){ zooKeeper.setData(PREFIX_SYNC, "hello6data".getBytes(), -1); } Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); }else if(Event.EventType.NodeDataChanged == event.getType()){ try { zooKeeper.getData(PREFIX_SYNC, true, new IDataCallback(), null); } catch (Exception e) { e.printStackTrace(); } } } } } class IDataCallback implements AsyncCallback.DataCallback { public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) { System.out.println("watch rc::" + rc + ", path::" + path + ", ctx::" + ctx +", data::" + new String(data)); System.out.println("watch czxid::"+stat.getCzxid()+",mzxid::" + stat.getMzxid() + ",version::" + stat.getVersion()); } }
控制台
2.6 更新数据
在更新数据时,setData方法存在一个version参数,其用于指定节点的数据版本,表明本次更新操作是针对指定的数据版本进行的,但是,在getData方法中,并没有提供根据指定数据版本来获取数据的接口,那么,这里为何要指定数据更新版本呢,这里方便理解,可以等效于CAS(compare and swap),对于值V,每次更新之前都会比较其值是否是预期值A,只有符合预期,才会将V原子化地更新到新值B。Zookeeper的setData接口中的version参数可以对应预期值,表明是针对哪个数据版本进行更新,假如一个客户端试图进行更新操作,它会携带上次获取到的version值进行更新,而如果这段时间内,Zookeeper服务器上该节点的数据已经被其他客户端更新,那么其数据版本也会相应更新,而客户端携带的version将无法匹配,无法更新成功,因此可以有效地避免分布式更新的并发问题。
2.6.1 同步方式
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestSetNodeDataSync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "10.0.40.10:2181"; private static final String PREFIX_SYNC = "/mytest-sync-setData2-"; private static ZooKeeper zooKeeper ; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestSetNodeDataSync()); countDownLatch.await(); zooKeeper.create(PREFIX_SYNC, "hello6data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("the data of node:" + new String(zooKeeper.getData(PREFIX_SYNC, true, null))); Stat stat = zooKeeper.setData(PREFIX_SYNC, "hello6data".getBytes(), -1); System.out.println("czxid::"+stat.getCzxid()+",mzxid::" + stat.getMzxid() + ",version::" + stat.getVersion()); Stat stat2 = zooKeeper.setData(PREFIX_SYNC, "hello6data".getBytes(), stat.getVersion()); System.out.println("czxid::"+stat2.getCzxid()+",mzxid::" + stat2.getMzxid() + ",version::" + stat2.getVersion()); try { zooKeeper.setData(PREFIX_SYNC, "hello6data".getBytes(), stat.getVersion()); } catch (Exception e) { System.out.println("exception: " + e); } Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); }else if(Event.EventType.NodeDataChanged == event.getType()){ try { System.out.println("watch the data of:" + event.getPath() + " is::" + new String(zooKeeper.getData(event.getPath(), true, null))); } catch (Exception e) { e.printStackTrace(); } } } } }
控制台
2.6.2 异步方式
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestSetNodeDataASync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "10.0.40.10:2181"; private static final String PREFIX_SYNC = "/mytest-async-setData4-"; private static ZooKeeper zooKeeper ; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestSetNodeDataASync()); countDownLatch.await(); zooKeeper.create(PREFIX_SYNC, "hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); zooKeeper.setData(PREFIX_SYNC, "hello2".getBytes(), -1, new StatCallback(), null); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); } } } } class StatCallback implements AsyncCallback.StatCallback { public void processResult(int rc, String path, Object ctx, Stat stat) { System.out.println("rc:"+rc + ", path:" + path + ",ctx:" + ctx + ", stat:" + stat); } }
控制台
rc(ResultCode)为0,表明成功更新节点数据。
2.7 检查节点是否存在
2.7.1 同步方式
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestExistSync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "10.0.40.10:2181"; private static final String PREFIX_SYNC = "/mytest-sync-exist-"; private static ZooKeeper zooKeeper ; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestExistSync()); countDownLatch.await(); zooKeeper.exists(PREFIX_SYNC, true); zooKeeper.create(PREFIX_SYNC, "hello6data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); zooKeeper.setData(PREFIX_SYNC, "hello6data".getBytes(), -1); zooKeeper.delete(PREFIX_SYNC, -1); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ try { if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); }else if(Event.EventType.NodeDataChanged == event.getType()){ System.out.println("node " + event.getPath() + " changed." ); zooKeeper.exists(event.getPath(), true); }else if(Event.EventType.NodeCreated == event.getType()){ System.out.println("node " + event.getPath() + " created."); zooKeeper.exists(event.getPath(), true); }else if(Event.EventType.NodeDeleted == event.getType()){ System.out.println("node " + event.getPath() + " deleted."); zooKeeper.exists(event.getPath(), true); } } catch (Exception e) { e.printStackTrace(); } } } }
控制台
2.7.2 异步方式
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestExistASync implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "10.0.40.10:2181"; private static final String PREFIX_SYNC = "/mytest-async-exist8-"; private static ZooKeeper zooKeeper ; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestExistASync()); countDownLatch.await(); zooKeeper.exists(PREFIX_SYNC, true, new IStaCallback(), null); zooKeeper.create(PREFIX_SYNC, "111".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zooKeeper.setData(PREFIX_SYNC, "222".getBytes(), -1); //判断存在 并加监听 zooKeeper.exists(PREFIX_SYNC + "/c2", true, new IStaCallback(), null); zooKeeper.create(PREFIX_SYNC + "/c2", "111".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zooKeeper.delete(PREFIX_SYNC + "/c2", -1); // zooKeeper.exists(PREFIX_SYNC , true, new IStaCallback(), null); //上面修改数据 那步 对PREFIX_SYNC添加了一个监听 zooKeeper.delete(PREFIX_SYNC, -1); Thread.sleep(Integer.MAX_VALUE); } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ try { if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); }else if(Event.EventType.NodeDataChanged == event.getType()){ System.out.println("node " + event.getPath() + " changed." ); zooKeeper.exists(event.getPath(), true, new IStaCallback(), null); }else if(Event.EventType.NodeCreated == event.getType()){ System.out.println("node " + event.getPath() + " created."); zooKeeper.exists(event.getPath(), true, new IStaCallback(), null); }else if(Event.EventType.NodeDeleted == event.getType()){ System.out.println("node " + event.getPath() + " deleted."); zooKeeper.exists(event.getPath(), true, new IStaCallback(), null); } } catch (Exception e) { e.printStackTrace(); } } } } class IStaCallback implements AsyncCallback.StatCallback { public void processResult(int rc, String path, Object ctx, Stat stat) { System.out.println("rc:" + rc + ",path: " + path + ",ctx:" + ctx + ", stat:" + stat); } }
控制台
rc:-101,path: /mytest-async-exist8-,ctx:null, stat:null node /mytest-async-exist8- created. rc:0,path: /mytest-async-exist8-,ctx:null, stat:8590337352,8590337352,1526279675044,1526279675044,0,0,0,0,3,0,8590337352 node /mytest-async-exist8- changed. rc:0,path: /mytest-async-exist8-,ctx:null, stat:8590337352,8590337353,1526279675044,1526279675095,1,0,0,0,3,0,8590337352 rc:-101,path: /mytest-async-exist8-/c2,ctx:null, stat:null node /mytest-async-exist8-/c2 created. rc:0,path: /mytest-async-exist8-/c2,ctx:null, stat:8590337354,8590337354,1526279675128,1526279675128,0,0,0,0,3,0,8590337354 node /mytest-async-exist8-/c2 deleted. rc:-101,path: /mytest-async-exist8-/c2,ctx:null, stat:null node /mytest-async-exist8- deleted. rc:-101,path: /mytest-async-exist8-,ctx:null, stat:null
rc:-101 节点不存在去
2.8 权限相关
zookeeper使用ACL机制来实现权限控制, ACL机制主要分为3个方面,权限模式,权限ID和权限
2.8.1 权限模式
1) IP
ip模式是指权限针对这个ip而设置的,比如"ip:192.168.0.6",即允许这个ip访问数据节点
2) digest
digest模式是最常用的一种模式,形如"username:password"的方式。
3) world
该模式对所有用户开放
4) super
超级管理员模式。需要在zkServer.sh中配置,形如"super:password" ,需要重启服务器
2.8.2 权限ID
根据不同模式 授权给的不同对象, ip模式为ip地址, digest模式为username
2.8.2 权限
即允许的操作 CRUD等
2.8.4 删除节点+权限
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.concurrent.CountDownLatch; /** * @Author: rocky * @Date: Created in 2018/5/13. */ public class ZookeeperTestAcl implements Watcher { private static final CountDownLatch countDownLatch = new CountDownLatch(1); private static final String ADDRESS = "10.0.40.10:2181"; private static final String PREFIX_SYNC = "/mytest-sync-acl-"; private static ZooKeeper zooKeeper ; public static void main(String[] args) throws IOException, InterruptedException, KeeperException { try { zooKeeper = new ZooKeeper(ADDRESS, 5000, new ZookeeperTestAcl()); countDownLatch.await(); zooKeeper.addAuthInfo("digest", "true".getBytes()); zooKeeper.create(PREFIX_SYNC, "111".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT); zooKeeper.create(PREFIX_SYNC+"/c2", "222".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL); ZooKeeper zk2 = new ZooKeeper(ADDRESS, 5000, null); try { zk2.delete(PREFIX_SYNC+"/c2", -1); } catch (Exception e) { System.out.println("delete exception: " + e); } ZooKeeper zk3 = new ZooKeeper(ADDRESS, 5000, null); zk3.addAuthInfo("digest", "true".getBytes()); zk3.delete(PREFIX_SYNC+"/c2", -1); System.out.println("delete mytest-sync-acl-/c2 success"); ZooKeeper zk4 = new ZooKeeper(ADDRESS, 5000, null); zk4.delete(PREFIX_SYNC, -1); System.out.println("delete mytest-sync-acl- success"); Thread.sleep(Integer.MAX_VALUE); } catch (Exception e) { System.out.println("exception ::" +e); } } public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected == event.getState()){ if(Event.EventType.None == event.getType() && null == event.getPath()){ countDownLatch.countDown(); } } } }
控制台
说明:
可以看到,第一次我们使用无权限的zk2去删除,显然会报错,第二次我们使用带权限的zk3去操作,子节点被删除成功,但是当我们使用zk4去执行删除操作的时候并没有指定任何权限,依然能够删除其父节点,说明zk在进行删除操作的时候,其权限的作用范围是其子节点。也就是说,当我们对一个节点添加了权限之后我们依然可以随意删除该节点但是对于这个节点的子节点,就必须拥有相应的权限才能删除。而且zk原生api不支持递归删除,即在存在子节点的情况下,不允许删除其父节点。