zookeeper之java客户端调用API(四)

因为我用的是Eclipse,。就下载了zookeeper的插件,可以显示集群的节点情况,根据编译工具的不同自行下载
下面部分程序来自Zookeeper API,会有少许不同

java中关于zookeeper的操作方法大体分为下面这些

  1. connect - 连接到ZooKeeper集合
  2. create- 创建znode
  3. exists- 检查znode是否存在及其信息
  4. getData - 从特定的znode获取数据
  5. setData - 在特定的znode中设置数据
  6. getChildren - 获取特定znode中的所有子节点
  7. delete - 删除特定的znode及其所有子项
  8. close - 关闭连接

1、java客户端连接zookeepr集群

需要的jar包

 <dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.14</version>
</dependency>

连接类,也算是工具类,为下面的创建节点,删除节点等做铺垫

public class ZooKeeperConnection {

   // 定义zookeeper的对象
   private ZooKeeper zoo;
   final CountDownLatch connectedSignal = new CountDownLatch(1);
   // 连接的方法
   public ZooKeeper connect(String host) throws IOException,InterruptedException {	
      zoo = new ZooKeeper("192.168.137.131:2181",5000,new Watcher() {//这个是先连接验证的zookeeper的IP:端口		
         public void process(WatchedEvent we) {
            if (we.getState() == KeeperState.SyncConnected) {//判定是否连接成功,执行完就会被删除,
            //还有很多其他getState(),下面表格有几种
               connectedSignal.countDown();//解锁
            }
         }
      });		
      connectedSignal.await();//等待连接成功解锁
      return zoo;
   }
   //关闭连接的方法
   public void close() throws InterruptedException {
      zoo.close();
   }
}

下面是百度翻译外加自己理解,来自Enum Watcher.Event.KeeperState

连接状态解释
Disconnected断开连接(不管任何原因)返回
Expired集群已过期
SyncConnected处于连接状态(意味着连接成功,只要连接到集群的一个节点就可以)
AuthFailed身份验证失败

2、创建节点

public class ZKCreate {
   // 创建zookeeper对象
   private static ZooKeeper zk;
   // 创建连接对象
   private static ZooKeeperConnection conn;
   // 创建节点的方法
   public static void create(String path, byte[] data) throws 
      KeeperException,InterruptedException {
      //参数为地址,数据,ACL:访问控制列表,节点类型:临时顺序或两者。后两个可以参考下面的表格
      zk.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE,
      CreateMode.PERSISTENT);
   }

   public static void main(String[] args) {
      // 节点的路径
      String path = "/MyFirstZnode"; 
      // 数据转成byte数组
      byte[] data = "My first zookeeper app".getBytes(); 	
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("192.168.137.131");//在连接中想往哪个zookeeper的IP添加,
         //不要以为工具类里写了这里就不用写,如果不写是不行的
         create(path, data); // 根据指定节点创建节点,填充数据
         conn.close();  //关闭连接
      } catch (Exception e) {
         System.out.println(e.getMessage()); //Catch error message
      }
   }
}

在这里插入图片描述
ZooDefs.Ids 的参数

参数名解释
OPEN_ACL_UNSAFE完全开放的ACL,任何连接的客户端都可以操作该属性znode
CREATOR_ALL_ACL只有创建者才有ACL权限
READ_ACL_UNSAFE只能读取ACL

CreateMode:节点的类型,即临时顺序或两者
下面是参数名和及时(百度翻译请见谅)

参数名解释
EPHEMERAL当客户端断开连接时,znode将被删除。
EPHEMERAL_SEQUENTIALznode将在客户机断开连接时被删除,其名称将添加一个单调递增的数字。
PERSISTENT当客户端断开连接时,znode不会自动删除。
PERSISTENT_SEQUENTIAL当客户机断开连接时,znode不会自动删除,其名称将添加一个单调递增的数字。

3、检查节点是否存在

public class ZKExists {
   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;
   //检查节点是否存在,返回Stat元数据结构,这个数据结构是每个节点都有的
   public static Stat znode_exists(String path) throws
      KeeperException,InterruptedException {
      return zk.exists(path, true); //这个查询的最重要的语句
   }
   public static void main(String[] args) throws InterruptedException,KeeperException {
      String path = "/MyFirstZnode"; // 想要查询是否存在的节点			
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("192.168.137.131"); //zookeeper集群的某个节点的IP
         Stat stat = znode_exists(path); // 接收查询节点是否存在方法的返回值				
         if(stat != null) {//判定是否为空,为空说明该节点不存在
            System.out.println("Node exists and the node version is " +
            stat.getVersion());
         } else {
            System.out.println("Node does not exists");
         }
				
      } catch(Exception e) {
         System.out.println(e.getMessage()); // Catches error messages
      }
   }
}

在这里插入图片描述
这里注意zk.exists(path, true),
有两种,这只是一种
还有一种exists(String path, Watcher watcher)
boolean类型的是是否监视这个znode,而new一个新的是覆盖前一个Watcher肯定会监视

4、获取节点的数据data

这个是在上面判定节点是否存在的基础商行加了一些东西而已,因为上面已经获取到元数据了

public class ZKGetData {

   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;
   public static Stat znode_exists(String path) throws 
      KeeperException,InterruptedException {
      return zk.exists(path,true);
   }

   public static void main(String[] args) throws InterruptedException, KeeperException {
      String path = "/MyFirstZnode";
      final CountDownLatch connectedSignal = new CountDownLatch(1);	
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("192.168.137.131");
         Stat stat = znode_exists(path);	//	到这都没什么变化	
         if(stat != null) {
            byte[] b = zk.getData(path, new Watcher() {		//这里面可以先不用管,这是监听设置,当触发监听时里面才能执行	,创建,删除,修改触发监听
               public void process(WatchedEvent we) {					
                 if (we.getType() == Event.EventType.None) {//连接状态发生变更
                     switch(we.getState()) {
                        case Expired: //表示客户端和服务端超过timeout了,彻底断开连接了
                        connectedSignal.countDown();
                        break;
                     }						
                  } else {
                     String path = "/MyFirstZnode";			
                     try {
                        byte[] bn = zk.getData(path,
                        false, null);
                        String data = new String(bn,
                        "UTF-8");//字符编码
                        System.out.println(data);
                        connectedSignal.countDown();							
                     } catch(Exception ex) {
                        System.out.println(ex.getMessage());
                     }
                  }
               }
            }, null);
				
            String data = new String(b, "UTF-8");
            System.out.println("正常逻辑data输出的是这");
            System.out.println(data);
            connectedSignal.await();
				
         } else {
            System.out.println("Node does not exists");
         }
      } catch(Exception e) {
        System.out.println(e.getMessage());
      }
   }
}

在这里插入图片描述

5、插入data(会把原来的覆盖)

public class ZKSetData {
   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;

   // 节点信息插入方法
   public static void update(String path, byte[] data) throws
      KeeperException,InterruptedException {
      zk.setData(path, data, zk.exists(path,true).getVersion());//插入信息:路径,数据,版本
      //这里的版本也可以是-1;它是递增的,不过如果你要是想模仿原子操作,就需要判定版本问题了,否则-1就可以
   }

   public static void main(String[] args) throws InterruptedException,KeeperException {
      String path= "/MyFirstZnode";
      byte[] data = "First".getBytes(); //把字符串First转成byte数组		
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("192.168.137.131");
         update(path, data); // 调用上面的修改方法
      } catch(Exception e) {
         System.out.println(e.getMessage());
      }
   }
}

在这里插入图片描述
这注意Version(版本)问题,更新节点对版本有要求吗?

6、获取子节点

首先创建一个父节点和子节点
在这里插入图片描述

下面是获得子节点的程序

public class ZKGetChildren {
   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;

   // 节点的元数据结构
   public static Stat znode_exists(String path) throws 
      KeeperException,InterruptedException {
      return zk.exists(path,true);
   }
   public static void main(String[] args) throws InterruptedException,KeeperException {
      String path = "/MyFirstZnode"; // 父节点的路径
		
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("192.168.137.131");
         Stat stat = znode_exists(path); // 调用上面的获得节点的元数据的方法
         if(stat!= null) {	//先判定父节点是否存在
            List <String> children = zk.getChildren(path, false);//获得孩子节点的集合
            for(int i = 0; i < children.size(); i++) {
            	System.out.println(children.get(i)); //父节点的孩子节点
            }
          } else {
            System.out.println("Node does not exists");
         }

      } catch(Exception e) {
         System.out.println(e.getMessage());
      }

   }

}

在这需要注意是三点:

  1. zk.getChildren(path, false)有多种参数,可以true也可以new一个Watcher
  2. 如果想获得孩子节点data,这样的方法就是获得名字的,还是从getData 重新获取数据吧
  3. 这不要以为父节点没有数据了,当成文件夹啦,它还是节点

7、删除节点

public class ZKDelete {
   private static ZooKeeper zk;
   private static ZooKeeperConnection conn;

   // 删除方法
   public static void delete(String path) throws KeeperException,InterruptedException {
      zk.delete(path,zk.exists(path,true).getVersion());
      
   }
   public static void main(String[] args) throws InterruptedException,KeeperException {
      String path = "/MyFirstZnode"; //节点路径		
      try {
         conn = new ZooKeeperConnection();
         zk = conn.connect("192.168.137.131");//zookeeper集群的一个节点
         delete(path); //调用上面的删除方法
      } catch(Exception e) {
         System.out.println(e.getMessage()); // catches error messages
      }
   }
}

这里需要注意的:

  1. 删除没有子节点的节点没有问题,但是删除一个有子节点的节点会报错
    KeeperErrorCode = Directory not empty for (节点路径)
  2. 这是java客户端,不像命令行有删除节点和子节点的,对于有子节点的可以先遍历是否有子节点,删除子节点再删父节点
  3. 临时节点不允许有子节点,所以有子节点的肯定是永久节点

8、上面的程序中有很多涉及到Watcher的

关于监听器你可以认为是一种一次性的监听器,用过一次就会被删除,当然如果需要,用过一次删除后你可以手动再添加上,
如果有必要就加,没有就不加,这个Watcher肯定会分发到所有节点,会造成浪费

关于监听器里面的事件什么的上面程序上有很多,表格上也有很多它的参数

还有很多时间类型没写,大家可以参考ZooKeeper的Watch事件类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值