• Java操作zookeeper


    Java操作zookeeper总共有三种方式:

    1.原生的Java API

    2.zkclient

    3.curator

     第一种实现代码:

    pom.xml

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

     示例的java代码如下:

    package zook;
    
    import java.io.IOException;
    import java.util.concurrent.CountDownLatch;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.WatchedEvent;
    import org.apache.zookeeper.Watcher;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.Watcher.Event.KeeperState;
    import org.apache.zookeeper.ZooDefs;
    
    public class App {
    
        public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
            String connStr = "192.168.126.128:2181";
            CountDownLatch countDown = new CountDownLatch(1);
            
            Watcher watcher=new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if (event.getState() == KeeperState.SyncConnected) {
                        System.err.println("eventType:"+event.getType());
                        if(event.getType()==Event.EventType.None){
                            countDown.countDown();
                        }else if(event.getType()==Event.EventType.NodeCreated){
                            System.out.println("listen:节点创建");
                        }else if(event.getType()==Event.EventType.NodeChildrenChanged){
                            System.out.println("listen:子节点修改");
                        }
                    }
                }
            };
            
            ZooKeeper zookeeper = new ZooKeeper(connStr, 5000,watcher );
            countDown.await();
    
            //注册监听,每次都要重新注册,否则监听不到        
            zookeeper.exists("/top/jinyong", watcher);
            
            // 创建节点
            String result = zookeeper.create("/top/jinyong", "一生一世".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            System.out.println(result);
            
            Thread.sleep(10);
    
            // 获取节点
            byte[] bs = zookeeper.getData("/top/jinyong", true, null);
            result = new String(bs);
            System.out.println("创建节点后的数据是:" + result);
    
            // 修改节点
            zookeeper.setData("/top/jinyong", "I love you".getBytes(), -1);
            
            Thread.sleep(10);
    
            bs = zookeeper.getData("/top/jinyong", true, null);
            result = new String(bs);
            System.out.println("修改节点后的数据是:" + result);
    
            // 删除节点
            zookeeper.delete("/top/jinyong", -1);
            System.out.println("节点删除成功");
        }
    
    }
    View Code

     说明:

    1.会话连接是异步的,需要自己去处理。此处用的CountDownLatch

    2.Watch需要重复注册,不然就不能生效,比如开始的zookeeper.exists("/top/jinyong", watcher);就是为了注册监听

    3.开发的复杂性还是比较高的

    4.不支持多节点删除和创建。需要自己去递归。后面有一个关于递归的示例。

    第二种实现:

    pom.xml

    <dependency>
        <groupId>com.101tec</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.10</version>
    </dependency>

     示例的Java代码如下:

    package zook;
    
    import java.util.List;
    
    import org.I0Itec.zkclient.IZkChildListener;
    import org.I0Itec.zkclient.IZkDataListener;
    import org.I0Itec.zkclient.IZkStateListener;
    import org.I0Itec.zkclient.ZkClient;
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.Watcher.Event.KeeperState;
    
    public class Client {
    
        public static void main(String[] args) throws InterruptedException {
            String connStr = "192.168.126.128:2181";
            ZkClient zk = new ZkClient(connStr);
    
            // 注册【数据】事件
            zk.subscribeDataChanges("/top/zhuzhu", new IZkDataListener() {
    
                @Override
                public void handleDataDeleted(String arg0) throws Exception {
                    System.err.println("数据删除:" + arg0);
    
                }
    
                @Override
                public void handleDataChange(String arg0, Object arg1) throws Exception {
                    System.err.println("数据修改:" + arg0 + "------" + arg1);
    
                }
            });
    
            zk.subscribeChildChanges("/top", new IZkChildListener() {
    
                @Override
                public void handleChildChange(String arg0, List<String> arg1) throws Exception {
                    System.err.println("子节点发生变化:" + arg0);
                    arg1.forEach(f -> {
                        System.out.println("content:" + f);
                    });
                }
            });
    
            List<String> list = zk.getChildren("/");
            list.forEach(e -> {
                System.out.println(e);
            });
    
            String res = zk.create("/top/zhuzhu", "I love you", CreateMode.PERSISTENT);
            System.out.println("创建节点/top/zhuzhu成功:" + res);
    
            zk.writeData("/top/zhuzhu", "forerver");
            System.out.println("修改节点/top/zhuzhu数据成功");
    
            res = zk.readData("/top/zhuzhu");
            System.out.println("节点数据:" + res);
    
            Thread.sleep(1000);
    
            zk.delete("/top/zhuzhu");
            System.out.println("删除节点/top/zhuzhu成功");
            
            Thread.sleep(1000);
            
            System.out.println("------------------------------------------------");
            
            for (int i = 0; i < 10; i++) {
                zk.create("/top/zhuzhu", "I love you", CreateMode.PERSISTENT);
                Thread.sleep(1000);
                zk.delete("/top/zhuzhu");
                Thread.sleep(1000);
            }
    
        }
    
    }
    View Code

     说明:

    1.subscribe开头的为注册监听的一些方法

    2.addAuthInfo和setAcl为权限相关控制

    3.普通使用这种方式还是值得推荐的

    第三种实现:

    pom.xml

    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>2.11.0</version>
    </dependency>

     示例的Java代码如下:

    package zook;
    
    import org.apache.curator.framework.CuratorFramework;
    import org.apache.curator.framework.CuratorFrameworkFactory;
    import org.apache.curator.framework.recipes.cache.PathChildrenCache;
    import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
    import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
    import org.apache.curator.retry.ExponentialBackoffRetry;
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.data.Stat;
    
    public class Curator {
    
        public static void main(String[] args) throws Exception {
            String connStr = "192.168.23.24:2181";
            CuratorFramework cur=CuratorFrameworkFactory.builder()
                .connectString(connStr)
                .connectionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000,3))
                .build();
            cur.start();//连接
            
            //创建监听
            PathChildrenCache cache=new PathChildrenCache(cur,"/top",true);
            cache.start();
            cache.rebuild();
            cache.getListenable().addListener(new PathChildrenCacheListener() {
                @Override
                public void childEvent(CuratorFramework framwork, PathChildrenCacheEvent event) throws Exception {
                    System.err.println("节点发生变化:"+event.getType());
                }
            });                
            
            Stat stat=cur.checkExists().forPath("/top/zhuzhu");
            if(stat!=null){
                System.out.println("【/top/zhuzhu】节点存在,直接删除");
                cur.delete().forPath("/top/zhuzhu");
            }
            cur.delete().forPath("/top/zhuzhu");
            
            System.in.read();
            
            System.out.println("准备创建【/top/zhuzhu】");
            cur.create().withMode(CreateMode.PERSISTENT)
                .forPath("/top/zhuzhu", "love forever".getBytes());
            System.out.println("节点【/top/zhuzhu】创建成功");
            
            Thread.sleep(1000);
            
            byte[] bs=cur.getData().forPath("/top/zhuzhu");
            System.out.println("数据:"+new String(bs));
            
            Thread.sleep(1000);
            
            cur.delete().forPath("/top/zhuzhu");
            
            Thread.sleep(1000);
    
        }
    
        
        /**
         * 三种watcher来做节点的监听
         * pathcache   监视一个路径下子节点的创建、删除、节点数据更新
         * NodeCache   监视一个节点的创建、更新、删除
         * TreeCache   pathcaceh+nodecache 的合体(监视路径下的创建、更新、删除事件),
         * 缓存路径下的所有子节点的数据
         */
    
        public static void main1(String[] args) throws Exception {        
            String connStr = "192.168.23.24:2181";
            CuratorFramework curatorFramework=CuratorFrameworkFactory.builder()
                .connectString(connStr)
                .connectionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000,3))
                .build();
            curatorFramework.start();
    
            /**
             * 节点变化NodeCache
             */
           /* NodeCache cache=new NodeCache(curatorFramework,"/curator",false);
            cache.start(true);
    
            cache.getListenable().addListener(()-> System.out.println("节点数据发生变化,变化后的结果" +
                    ":"+new String(cache.getCurrentData().getData())));
    
            curatorFramework.setData().forPath("/curator","菲菲".getBytes());*/
    
    
            /**
             * PatchChildrenCache
             */
    
            PathChildrenCache cache=new PathChildrenCache(curatorFramework,"/event",true);
            cache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
            cache.rebuild();
            // Normal / BUILD_INITIAL_CACHE /POST_INITIALIZED_EVENT
    
            cache.getListenable().addListener((curatorFramework1,pathChildrenCacheEvent)->{
                switch (pathChildrenCacheEvent.getType()){
                    case CHILD_ADDED:
                        System.out.println("增加子节点");
                        break;
                    case CHILD_REMOVED:
                        System.out.println("删除子节点");
                        break;
                    case CHILD_UPDATED:
                        System.out.println("更新子节点");
                        break;
                    default:break;
                }
            });
    
          //  curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/event","event".getBytes());
           // TimeUnit.SECONDS.sleep(1);
           // System.out.println("1");
    //        curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/event/event1","1".getBytes());
    //        TimeUnit.SECONDS.sleep(1);
    //        System.out.println("2");
    //
    //        curatorFramework.setData().forPath("/event/event1","222".getBytes());
    //        TimeUnit.SECONDS.sleep(1);
    //        System.out.println("3");
    
            curatorFramework.delete().forPath("/event/event1");
            System.out.println("4");
    
    
    
    
            System.in.read();
    
        }
    
    }
    View Code

     说明:

    1.支持事务

    2.支持Flush写法

    3.开始测试多次程序启动就执行删除节点,而监听的结果确实新增,后来加了cache.rebuild();代码就没问题了。跟源码,在cache.start()里面有一个构造函数也是调用了rebuild方法的。

    4.功能还是比较强大的。高级功能都会用到这种方式

    最后贴一个原生API的递归操作方式:

    package zook;
    
    import java.io.IOException;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.WatchedEvent;
    import org.apache.zookeeper.Watcher;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.data.Stat;
    import org.apache.zookeeper.Watcher.Event.EventType;
    import org.apache.zookeeper.Watcher.Event.KeeperState;
    import org.apache.zookeeper.ZooDefs;
    
    public class ZookManager {
        ZooKeeper zookeeper = null;
    
        public ZookManager(String connStr) throws IOException, InterruptedException {
            CountDownLatch latch = new CountDownLatch(1);
            zookeeper = new ZooKeeper(connStr, 5000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if (event.getType() == EventType.None) {
                        if (event.getState() == KeeperState.SyncConnected) {
                            latch.countDown();
                        } else {
                            System.out.println("连接失败.");
                            latch.countDown();
                        }
                    }
                }
    
            });
            latch.await();
        }
    
        /** 创建节点,不存在父节点将新增,如果节点已经存在将抛出异常 **/
        public String create(String path, String val) throws KeeperException, InterruptedException {
            if (!checkPath(path)) {
                return "";
            }
    
            String p = getParentPath(path);
            cycleCreate(p);
    
            String url = zookeeper.create(path, val.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            return url;
        }
    
        /** 设置节点的数据,如果节点不存在将新增该节点  **/
        public Stat setData(String path, String val) throws KeeperException, InterruptedException {
            if (!checkPath(path)) {
                return null;
            }
    
            cycleCreate(path);
            return zookeeper.setData(path, val.getBytes(), -1);
        }
    
        /** 删除节点,如果存在子节点将递归删除 
         * @throws InterruptedException 
         * @throws KeeperException **/
        public void delete(String path) throws KeeperException, InterruptedException {
            if (!checkPath(path)) {
                return;
            }
    
            List<String> chidren = zookeeper.getChildren(path, false);
            for (String p : chidren) {
                delete(path + "/" + p);
            }
            zookeeper.delete(path, -1);
        }
    
        private void cycleCreate(String path) throws KeeperException, InterruptedException {
            Stat stat = zookeeper.exists(path, null);
            if (stat == null) {
                String p = getParentPath(path);
                cycleCreate(p);// 递归
                // 创建
                zookeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
        }
    
        /**
         * 检查目录是否正确
         * @param path
         * @return
         */
        private boolean checkPath(String path) {
            if (!path.startsWith("/")) {
                System.err.println("路径必须以/开头:" + path);
                return false;
            }
            if (path.endsWith("/")) {
                System.err.println("路径不能以/结尾:" + path);
                return false;
            }
            if (path.contains("//")) {
                System.err.println("路径格式不对,存在连续的/:" + path);
                return false;
            }
            if (path.equals("/")) {
                System.err.println("路径格式不对,只有一个/:" + path);
                return false;
            }
            return true;
        }
    
        /**
         * 获得父级目录
         * @param path /root/abc
         * @return
         */
        private String getParentPath(String path) {
            int index = path.lastIndexOf("/");
            return path.substring(0, index);
        }
    
        public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
            ZookManager zoo = new ZookManager("192.168.23.24:2181");
            zoo.setData("/top/enjoy/abc", "abc");
            zoo.setData("/top/enjoy/bbb", "bbb");
            zoo.setData("/top/enjoy/ccc", "ccc");
            System.out.println("成功新增");        
            zoo.delete("/top/enjoy");
            System.out.println("成功删除");
        }
    }
  • 相关阅读:
    elementui form-item中多个字段校验
    Element-ui的 el-form 使用 v-if校验失灵问题
    fullcalendar title换行
    html拼接
    element-ui cascader 省市区 动态加载
    切换vue项目初始化路径
    用JavaScript获取当月第一天和最后一天
    小宝和小黑
    python目录
    3
  • 原文地址:https://www.cnblogs.com/duanjt/p/9896641.html
Copyright © 2020-2023  润新知