curator操作zookeeper

使用zookeeper原生API实现一些复杂的东西比较麻烦。所以,出现了两款比较好的开源客户端,对zookeeper的原生API进行了包装:zkClient和curator。后者是Netflix出版的,必属精品,也是最好用的zk的开源客户端。

一  curator基本API使用

推荐博客:https://www.cnblogs.com/java-zhao/p/7350945.html

https://www.cnblogs.com/nevermorewang/p/5815602.html    强烈推荐

pom

<dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
</dependency>

创建客户端

private static CuratorFramework client = CuratorFrameworkFactory.builder()
       .authorization("digest","admin:123".getBytes()) //创建客户端的时候授权 .connectString(
"ip:2181") .sessionTimeoutMs(50000) .connectionTimeoutMs(30000) .retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();

创建节点

      /**
          * 创建会话
          */
         client.start();
 
         /**
          * 创建节点
          * 注意:
          * 1 除非指明创建节点的类型,默认是持久节点
          * 2 ZooKeeper规定:所有非叶子节点都是持久节点,所以递归创建出来的节点,只有最后的数据节点才是指定类型的节点,其父节点是持久节点
          */
         client.create().forPath("/China");//创建一个初始内容为空的节点
         client.create().forPath("/America", "zhangsan".getBytes());
         client.create().withMode(CreateMode.EPHEMERAL).forPath("/France");//创建一个初始内容为空的临时节点
         client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/Russia/car", "haha".getBytes());//递归创建,/Russia是持久节点
         
         
         /**
          * 异步创建节点
          * 注意:如果自己指定了线程池,那么相应的操作就会在线程池中执行,如果没有指定,那么就会使用Zookeeper的EventThread线程对事件进行串行处理
          */
         client.create().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
             @Override
             public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                 System.out.println("当前线程:" + Thread.currentThread().getName() + ",code:" + event.getResultCode()
                                    + ",type:" + event.getType());
             }
         }, Executors.newFixedThreadPool(10)).forPath("/async-curator-my");
 
         client.create().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
             @Override
             public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                 System.out.println("当前线程:" + Thread.currentThread().getName() + ",code:" + event.getResultCode()
                                    + ",type:" + event.getType());
             }
         }).forPath("/async-curator-zookeeper");

获取节点数据

Stat stat = new Stat();
byte[] bytes = zk.curator.getData().storingStatIn(stat).forPath("/liuzhonghua");
System.out.println("路径/liuzhonghua的数据是:"+new String(bytes));
System.out.println("路径/liuzhonghua的数据的版本是:"+stat.getVersion());

 路径/liuzhonghua的数据是:lzh
 路径/liuzhonghua的数据的版本是:0

 

更新节点

client.setData().withVersion(4).forPath("/America", "lisi".getBytes());

删除节点

      /**
          * 删除节点
          */
         client.delete().forPath("/China");//只能删除叶子节点
         client.delete().deletingChildrenIfNeeded().forPath("/Russia");//删除一个节点,并递归删除其所有子节点
         client.delete().withVersion(5).forPath("/America");//强制指定版本进行删除
         client.delete().guaranteed().forPath("/America");//注意:由于一些网络原因,上述的删除操作有可能失败,使用guaranteed(),如果删除失败,会记录下来,只要会话有效,就会不断的重试,直到删除成功为止
    

创建Acl权限

        ArrayList<ACL> acls = new ArrayList<ACL>();
        Id id1=new Id("digest", DigestAuthenticationProvider.generateDigest("admin1:123"));
        Id id2=new Id("digest", DigestAuthenticationProvider.generateDigest("admin2:123"));
        acls.add(new ACL(ZooDefs.Perms.ADMIN,id1));
        acls.add(new ACL(ZooDefs.Perms.CREATE,id2));
        acls.add(new ACL(ZooDefs.Perms.ADMIN | ZooDefs.Perms.READ,id2));
        zk.curator.create().creatingParentsIfNeeded().withACL(acls).forPath("/liuzhonghua001/003","lzh".getBytes());

结果:

[zk: localhost:2181(CONNECTED) 5] getAcl /liuzhonghua001/003
'digest,'admin1:CC9El/l/qyakTrK/mNREkrSikQ0=
: a
'digest,'admin2:iZICqg+4cn1ouEHqGPuzGrop/M4=
: c
'digest,'admin2:iZICqg+4cn1ouEHqGPuzGrop/M4=
: ra
[zk: localhost:2181(CONNECTED) 6]

 设置Acl权限

 ArrayList<ACL> acls = new ArrayList<ACL>();
        Id id1=new Id("digest", DigestAuthenticationProvider.generateDigest("admin1:123"));
        Id id2=new Id("digest", DigestAuthenticationProvider.generateDigest("admin2:123"));
        acls.add(new ACL(ZooDefs.Perms.ADMIN,id1));
        acls.add(new ACL(ZooDefs.Perms.CREATE,id2));
        acls.add(new ACL(ZooDefs.Perms.ADMIN | ZooDefs.Perms.READ,id2));

zk.curator.setACL().withACL(acls).forPath("/liuzhonghua001/003");

 

curator实现事件监听

<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.12.0</version>
        </dependency>

对指定节点进行监听(监听指定节点本身的变化,包括节点本身的创建和节点本身数据的变化)

NodeCache nodeCache = new NodeCache(client,"/lzh");
        nodeCache.getListenable().addListener(new NodeCacheListener() {
                                                  @Override
                                                  public void nodeChanged() throws Exception {
                                                      System.out.println("新的节点数据:" + new String(nodeCache.getCurrentData().getData()));
                                                  }
                                              });
nodeCache.start(true);

监听子节点变化情况(1 新增子节点,2删除子节点,3数据改变)

/**
         * 监听子节点变化情况
         * 1 新增子节点
         * 2 删除子节点
         * 3 子节点数据变更
         */
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client,"/lzh",true);
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                switch (event.getType()){
                    case CHILD_ADDED:
                        System.out.println("新增子节点:" + event.getData().getPath());
                        break;
                    case CHILD_UPDATED:
                        System.out.println("子节点数据变化:" + event.getData().getPath());
                        break;
                    case CHILD_REMOVED:
                        System.out.println("删除子节点:" + event.getData().getPath());
                        break;
                    default:
                        break;
                }
            }
        });
        pathChildrenCache.start();
  • PathChildrenCache只会监听指定节点的一级子节点,不会监听节点本身(例如:“/book13”),也不会监听子节点的子节点(例如,“/book13/car/color”)

 

posted @ 2018-08-23 13:49  发疯的man  阅读(1943)  评论(0编辑  收藏  举报