Curator客户端的使用

1.前言

之前已经说了zookeeper的原生的API,我们也知道了原生api不足之处:

  • 超时重连,不支持自动
  • Watcher注册一次后则会失效
  • 不支持递归读写操作
    因此本篇博客所讲的Curator框架就是问了解决上述问题的

Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册,提供更多解决方案:如分布式锁以及Watcher和NodeExistsException异常等等。

接下来看一下具体的实现代码:

2.具体实现

连接客户端


public CuratorFramework client = null;
public static final String zkServerPath = "127.0.0.1:2181";

    /**
       * 同步创建zk示例,原生api是异步的
       *
       * curator链接zookeeper的策略:ExponentialBackoffRetry
       * baseSleepTimeMs:初始sleep的时间
       * maxRetries:最大重试次数
       * maxSleepMs:最大重试时间
       */
//    RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);

      /**
       * curator链接zookeeper的策略:RetryNTimes
       * n:重试的次数
       * sleepMsBetweenRetries:每次重试间隔的时间
       */
      //RetryPolicy retryPolicy = new RetryNTimes(3, 5000);

      /**
       * curator链接zookeeper的策略:RetryOneTime
       * sleepMsBetweenRetry:每次重试间隔的时间
       */
      RetryPolicy retryPolicy2 = new RetryOneTime(3000);

      /**
       * 永远重试,不推荐使用
       */
//    RetryPolicy retryPolicy3 = new RetryForever(retryIntervalMs)

      /**
       * curator链接zookeeper的策略:RetryUntilElapsed
       * maxElapsedTimeMs:最大重试时间
       * sleepMsBetweenRetries:每次重试间隔
       * 重试时间超过maxElapsedTimeMs后,就不再重试
       */
//    RetryPolicy retryPolicy4 = new RetryUntilElapsed(2000, 3000);



client = CuratorFrameworkFactory.builder()
   // .authorization("digest","id1:123456".getBytes())
      .connectString(zkServerPath)
      .sessionTimeoutMs(10000).retryPolicy(retryPolicy2)
      .namespace("workspace").build();
client.start();

boolean isZkCuratorStarted = cto.client.isZk34CompatibilityMode();
System.out.println("当前客户的状态:" + (isZkCuratorStarted ? "连接中" : "已关闭"));

输出:当前客户的状态:连接中

关闭客户端连接

public void closeZKClient() {
   if (client != null) {
      this.client.close();
   }
}

创建节点
可以递归创建

public  static void createNode(CuratorOperator cto) throws Exception {
   String path = "/super/n2";
   byte [] data = "ldd-data".getBytes();
   cto.client.create().creatingParentsIfNeeded()
         .withMode(CreateMode.PERSISTENT)
         .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
         .forPath(path,data);
}

更新节点

 public  static void updateNode(CuratorOperator cto) throws Exception{
   String path = "/super/n2";
byte[] newData = "new-data".getBytes();
cto.client.setData().withVersion(0).forPath(path, newData);
  }

删除节点

public static void deleteNode(CuratorOperator cto)throws Exception{
	  String path = "/super/n2";
          cto.client.delete()
           .guaranteed()                // 如果删除失败,那么在后端还是继续会删除,直到成功
           .deletingChildrenIfNeeded()  // 如果有子节点,就删除
           .withVersion(0)
           .forPath(path);
}

读取节点数据

public static void readNode(CuratorOperator cto)throws Exception{
    Stat stat = new Stat();
    String path = "/super/n2";
    byte[] data = cto.client
            .getData()
            .storingStatIn(stat)
            .forPath(path);
    System.out.println("data: "+new String(data));
    System.out.println("最新的版本号: "+stat.getVersion());
}

查询子节点

public static void selectChildNode(CuratorOperator cto)throws Exception{
 String path = "/super";
    List<String> list = cto.client
            .getChildren()
            .forPath(path);
    for(String list1:list){
        System.out.println(list1);
    }
}
输出n2
[zk: localhost:2181(CONNECTED) 32] ls /workspace/super
[n2]
[zk: localhost:2181(CONNECTED) 33] 

判断节点是否存在
如果没有此节点则返回null

public static void isExistNode(CuratorOperator cto)throws Exception{
 String path = "/super";
    Stat stat = cto.client
            .checkExists().forPath(path);
    System.out.println(stat);
}

读取数据添加Watcher

public static void readNodeByWatcher(CuratorOperator cto)throws Exception{
 String path = "/super/n2";

    byte[] data = cto.client
            .getData()
            // watcher 事件  当使用usingWatcher的时候,监听只会触发一次,监听完毕后就销毁
            .usingWatcher(new MyCuratorWatcher())
            //.usingWatcher(new MyWatcher()).forPath(nodePath);
            .forPath(path);
    System.out.println("data: "+new String(data));
}
public class MyCuratorWatcher implements CuratorWatcher {
    @Override
    public void process(WatchedEvent event)  {
        System.out.println("触发路径类型:"+event.getType());
    }
}
readNodeByWatcher(cto);
new Thread().sleep(1000000);
cto.closeZKClient();
[zk: localhost:2181(CONNECTED) 50] set /workspace/super/n2 n
将会输出:
触发路径类型:NodeDataChanged

节点缓存

 final NodeCache nodeCache = new NodeCache(cto.client,path);
      nodeCache.start(true);//如果不写参数默认是false
          if (nodeCache.getCurrentData() != null) {
   System.out.println("节点初始化数据为:" + new String(nodeCache.getCurrentData().getData()));
} else {
   System.out.println("节点初始化数据为空...");
}

nodeCache.getListenable().addListener(new NodeCacheListener() {
   public void nodeChanged() throws Exception {
      if (nodeCache.getCurrentData() == null) {
         System.out.println("空");
         return;
      }
      String data = new String(nodeCache.getCurrentData().getData());
      System.out.println("节点路径:" + nodeCache.getCurrentData().getPath() + "数据:" + data);
   }
});

当前客户的状态:连接中
节点初始化数据为:n
节点路径:/super/n2数据:n2
节点路径:/super/n2数据:n3
节点路径:/super/n2数据:n4
节点路径:/super/n2数据:n5
节点路径:/super/n2数据:n6

[zk: localhost:2181(CONNECTED) 49] set /workspace/super/n2 n
[zk: localhost:2181(CONNECTED) 50] set /workspace/super/n2 n
[zk: localhost:2181(CONNECTED) 51] set /workspace/super/n2 n2
[zk: localhost:2181(CONNECTED) 52] set /workspace/super/n2 n3
[zk: localhost:2181(CONNECTED) 53] set /workspace/super/n2 n4
[zk: localhost:2181(CONNECTED) 54] set /workspace/super/n2 n5
[zk: localhost:2181(CONNECTED) 55] set /workspace/super/n2 n6

子节点缓存
BUILD_INITIAL_CACHE 会打印数据

String childNodePathCache =  "/super";
// cacheData: 设置缓存节点的数据状态
final PathChildrenCache childrenCache = new PathChildrenCache(cto.client, childNodePathCache, true);
/**
 * StartMode: 初始化方式
 * POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件
 * NORMAL:异步初始化
 * BUILD_INITIAL_CACHE:同步初始化 会打印数据
 */
childrenCache.start(StartMode.BUILD_INITIAL_CACHE);

List<ChildData> childDataList = childrenCache.getCurrentData();
      System.out.println(childDataList.size());
System.out.println("当前数据节点的子节点数据列表:");
for (ChildData cd : childDataList) {
   String childData = new String(cd.getData());
   System.out.println(childData);
}

POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件

childrenCache.start(StartMode.POST_INITIALIZED_EVENT);

List<ChildData> childDataList = childrenCache.getCurrentData();
childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
          public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
              if (event.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)) {
                  System.out.println("子节点初始化ok...");
              }
 readNodeByWatcher(cto);
new Thread().sleep(100000);
 cto.closeZKClient();

子节点初始化ok...

Watcher类型触发:

childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
          public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
              if (event.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)) {
                  System.out.println("子节点初始化ok...");
              }
              else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){
         String path = event.getData().getPath();
                  System.out.println("添加新节点: "+path);
                //  System.out.println("data: "+event.getData());
         if (path.equals("/super/nn1")) {
            System.out.println("添加子节点:" + event.getData().getPath());
            System.out.println("子节点数据:" + new String(event.getData().getData()));
         } else if (path.equals("/super/ldd/e")) {
            System.out.println("添加不正确...");
         }

      }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){
         System.out.println("删除子节点:" + event.getData().getPath());
      }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
         System.out.println("修改子节点路径:" + event.getData().getPath());
         System.out.println("修改子节点数据:" + new String(event.getData().getData()));
      }
   }
});

new Thread().sleep(100000);
 cto.closeZKClient();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值