打开zookeeper集群
先体会一下原生API有多麻烦(可略过):
//地址 static final String ADDR = "192.168.171.128:2181,192.168.171.129:2181,192.168.171.130:2181"; //session超时时间 static final int SESSION_OUTTIME = 2000;//ms /** * 信号量,阻塞程序执行,用于等待zookeeper连接(异步的)成功,发送成功信号 */ static final CountDownLatch connectedSemaphore = new CountDownLatch(1); public static void main(String[] args) throws Exception { //创建zk客户端(异步连接) Watcher:监听连接 ZooKeeper zooKeeper = new ZooKeeper(ADDR, SESSION_OUTTIME, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { //获取事件的状态 Event.KeeperState keeperState = watchedEvent.getState(); Event.EventType eventType = watchedEvent.getType(); //如果是建立连接 if(Event.KeeperState.SyncConnected == keeperState){ if(Event.EventType.None == eventType){ //如果建立连接成功,则发送信号量,让后续阻塞程序向下执行 connectedSemaphore.countDown(); System.out.println("zk 建立连接"); } } } }); //进行阻塞,等待zk连接成功 connectedSemaphore.await(); //连接成功执行操作: //同步 路径(不允许递归创建), 数据 权限, 类型(PERSISTENT:持久) :临时节点只是一次session有效,用来实现分布式锁 String name = zooKeeper.create("/testRoot", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); String name1 = zooKeeper.create("/testRoot/child02", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); //异步 回调函数 , 回调的参数 zooKeeper.create("/testRoot/child01", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, new AsyncCallback.StringCallback() { @Override //服务端响应吗: 0 成功 传入的path 参数 实际创建的path public void processResult(int i, String s, Object o, String s1) { System.out.println(i+" "+s+" "+o.toString()+" "+s1); }},"param"); //删除 (路径必须是叶子节点,即没有下一级节点,不支持递归) //zooKeeper.delete("/testRoot/child01", -1);//版本号:-1表示删除所有的,像git一样,修改一次版本号加一,可删除指定版本号 //同样支持异步,和创建一样传入回调 //判断节点是否存在 System.out.println(zooKeeper.exists("/testRoot/child01", false));//也可传入watch,异步回调等 //获取 byte[] data = zooKeeper.getData("/testRoot", false, null); System.out.println(new String(data)); System.out.println(zooKeeper.getChildren("/testRoot", false)); //修改 zooKeeper.setData("/testRoot", "modify data root".getBytes(), -1); byte[] data1 = zooKeeper.getData("/testRoot", false, null); System.out.println(new String(data1)); Thread.sleep(3000);//休眠防止异步 zooKeeper.close();//释放资源
zkclient:
/** zookeeper地址 */ static final String CONNECT_ADDR = "192.168.171.128:2181,192.168.171.129:2181,192.168.171.130:2181"; /** session超时时间 */ static final int SESSION_OUTTIME = 5000;//ms public static void main(String[] args) { // 创建zkclient实例 ZkClient zkc=new ZkClient(new ZkConnection(CONNECT_ADDR,SESSION_OUTTIME),10000); //增 zkc.create("/test","测试zkclient",CreateMode.PERSISTENT);// 创建节点,可指定持久或者临时 zkc.create("/test/heyi","heyi",CreateMode.PERSISTENT);// 创建节点,可指定持久或者临时 zkc.createEphemeral("/haha","haha");//创建临时节点 zkc.createPersistent("/test/yaozhen","姚振");//创建持久节点,设置值必须有父节点 zkc.createPersistent("/320/houzheng",true);//支持递归创建,但是不能设置值,否则会报异常 //删 zkc.delete("/test/yaozhen"); zkc.deleteRecursive("/320");//递归删除,会删除节点下的子节点 //改 zkc.writeData("/test","新内容"); //查 boolean exists = zkc.exists("/test"); System.out.println(exists); zkc.readData("/jim",true);//如果节点为空返回null String readData = zkc.readData("/test"); System.out.println(readData); //获取子节点和阅读子节点数据 List<String> list = zkc.getChildren("/test"); for(String p : list){ System.out.println(p); String rp = "/test/" + p; String data = zkc.readData(rp); System.out.println("节点为:" + rp + ",内容为: " + data); } int i = zkc.countChildren("/test");//查询子节点数量 System.out.println(i);
相比之下zkclient简直太简单了!
watcher也特别简单:
子节点监听:
// 创建zkclient实例 ZkClient zkClient=new ZkClient(new ZkConnection(CONNECT_ADDR,SESSION_OUTTIME),10000); System.out.println("-----------"); //监听子节点变化(不监听数据变化,只监听节点的新增删除) IZkChildListener实现类 zkClient.subscribeChildChanges("/father",(x,y)->{//x:父路径, y:所有子节点路径集合 System.out.println("parentPath: " + x); System.out.println("currentChilds: " + y); }); Thread.sleep(2000); zkClient.createPersistent("/father");//父节点添加删除也会监听 Thread.sleep(1000); zkClient.createPersistent("/father/son","儿子"); Thread.sleep(1000); zkClient.createPersistent("/father/daughter","女儿"); Thread.sleep(1000); zkClient.delete("/father/son"); Thread.sleep(1000); zkClient.deleteRecursive("/father");
节点数据监听:
//监听节点数据变化,监听之前节点必须存在,不监听子节点 zkClient.createPersistent("/father", "1234"); zkClient.subscribeDataChanges("/father", new IZkDataListener() { @Override //节点数据变化 public void handleDataChange(String s, Object o) throws Exception { System.out.println("变更的节点为:" + s + ", 变更内容为:" + o); } @Override //节点删除 public void handleDataDeleted(String s) throws Exception { System.out.println("删除的节点为:" + s); } }); Thread.sleep(3000); zkClient.writeData("/father", "father");//-1:最新版本的数据 Thread.sleep(1000); zkClient.delete("/father");//节点删除野人不监听 Thread.sleep(1000);
状态监听:
//监听服务连接状态,可手动启动关闭zookeeper查看触发 zkClient.subscribeStateChanges(new IZkStateListener() { @Override public void handleStateChanged(Watcher.Event.KeeperState state) throws Exception { if(state==Watcher.Event.KeeperState.SyncConnected){ System.out.println("连接zookeeper成功"); }else if(state==Watcher.Event.KeeperState.Disconnected){ System.out.println("zookeeper断开"); }else System.out.println("other"+state); } @Override //连接关闭,过了session的设置时间,再连接session就会重置,触发监听 public void handleNewSession() throws Exception { System.out.println("newsession"); } }); Thread.sleep(Integer.MAX_VALUE);//用不关闭线程,一直监听
curator框架: