• Zookeeper Curator API 使用


    0. 原生 ZOOKEEPER JAVA API  http://www.cnblogs.com/rocky-fang/p/9030438.html

    1. 概述

    Curator采用cache封装对事件的监听,包括监听节点、子节点。主要有:

    NodeCache、PathChildrenCache、TreeCache

    2. 例子

    2.1 NodeCache

    监听节点本身的变化,当节点的状态发生变更后,回调NodeCacheListener

    代码

    package com.rocky.learn.curator;
    
    import org.apache.curator.RetryPolicy;
    import org.apache.curator.framework.CuratorFramework;
    import org.apache.curator.framework.CuratorFrameworkFactory;
    import org.apache.curator.framework.recipes.cache.ChildData;
    import org.apache.curator.framework.recipes.cache.NodeCache;
    import org.apache.curator.framework.recipes.cache.NodeCacheListener;
    import org.apache.curator.retry.ExponentialBackoffRetry;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.ZooKeeper;
    
    import javax.xml.ws.soap.Addressing;
    import java.io.IOException;
    import java.util.concurrent.CountDownLatch;
    
    /**
     * @Author: rocky
     * @Date: Created in 2018/5/14.
     */
    public class NodeCacheTest {
        private static final CountDownLatch countDownLatch = new CountDownLatch(1);
        private static final String ADDRESS = "10.0.40.10:2181";
        private static final String PREFIX_SYNC = "/mytest-curator";
        private static final String NAMESPACE = "mybase";
        private static CuratorFramework client;
        private static NodeCache nodeCache;
        static {
    //        client = CuratorFrameworkFactory.newClient(ADDRESS, 5000, 5000,
    //                new ExponentialBackoffRetry(1000, 3));
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            client = CuratorFrameworkFactory.builder()
                    .connectString(ADDRESS)
                    .sessionTimeoutMs(5000)
                    .connectionTimeoutMs(5000)
                    .retryPolicy(retryPolicy)
                    .namespace(NAMESPACE)
                    .build();
            client.start();
        }
        private static void initCache() throws Exception {
            client.create().forPath(PREFIX_SYNC);
            client.setData().forPath(PREFIX_SYNC,"hello curator..".getBytes());
            nodeCache = new NodeCache(client, PREFIX_SYNC);
            nodeCache.start(true);
            startCache(nodeCache);
        }
    
        private static void startCache(final NodeCache nodeCache) throws Exception {
            ChildData currentData = nodeCache.getCurrentData();
            System.out.println("1111:" + new String(currentData.getData()));
            nodeCache.getListenable().addListener(new NodeCacheListener() {
                public void nodeChanged() throws Exception {
                    System.out.println("data change..." + new String(nodeCache.getCurrentData().getData()));
                    countDownLatch.countDown();
                }
            });
            Thread.sleep(2000);
            if(client.checkExists().forPath(PREFIX_SYNC) != null){
                System.out.println("设置新内容。。。。");
                client.setData().forPath(PREFIX_SYNC, "2222".getBytes());
            }
        }
    
        public static void main(String[] args) throws Exception {
            initCache();
            countDownLatch.await();
        }
    }
    View Code

    控制台

    2.2. PathChildrenCache

    主要用来监听子节点并且不会对二级节点进行监听

    代码

    package com.rocky.learn.curator;
    
    import org.apache.curator.RetryPolicy;
    import org.apache.curator.framework.CuratorFramework;
    import org.apache.curator.framework.CuratorFrameworkFactory;
    import org.apache.curator.framework.recipes.cache.ChildData;
    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.data.Stat;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * @Author: rocky
     * @Date: Created in 2018/5/15.
     */
    public class PathCacheTest {
        private static final String PATH = "/mycache/test7";
        private static final String ADDRESS = "10.0.40.10:2181";
        private static final String BASE = "mybase";
        private static PathChildrenCache pathChildrenCache;
        private static CuratorFramework client;
        private static CountDownLatch countDownLatch = new CountDownLatch(1);
        private static CountDownLatch countDownLatch2 = new CountDownLatch(5);
        static {
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            client = CuratorFrameworkFactory.builder()
                    .connectString(ADDRESS)
                    .sessionTimeoutMs(5000)
                    .connectionTimeoutMs(5000)
                    .retryPolicy(retryPolicy)
    //                .namespace(BASE)
                    .build();
            client.start();
        }
    
        public static void main(String[] args) throws Exception {
            startCache();
            countDownLatch.await();
        }
    
        private static void startCache() throws Exception {
            pathChildrenCache = new PathChildrenCache(client, PATH, true);
            pathChildrenCache.start();
            for (int i = 1; i < 6; i++) {
                String newPath = PATH + "/child_" + i;
                String childNodeName = "child_" + i;
                client.create().creatingParentsIfNeeded().forPath(newPath, childNodeName.getBytes());
                countDownLatch2.countDown();
            }
            countDownLatch2.await();
            addListener(pathChildrenCache);
            for(final ChildData childData : pathChildrenCache.getCurrentData()){
                System.out.println("输出: child path :" + childData.getPath() +
                    ", child data: " + new String(childData.getData()));
            }
            Thread.sleep(2000);
            System.out.println("父节点设值......start");//不会有事件监听返回
            client.setData().forPath(PATH, "11111".getBytes());
            System.out.println("父节点设值......end");
            System.out.println("子节点 del....start");
            client.delete().forPath(PATH + "/child_1");
            System.out.println("子节点 del....end");
            Thread.sleep(2000);
            for(int j=1; j<3; j++){
                String newPath = PATH + "/child_2/" + j;
                String nodeName = "child_2_"+ j;
                client.create().forPath(newPath, nodeName.getBytes());
            }
            addListener(pathChildrenCache);
            System.out.println("二级节点 del...start");//不会有事件监听返回
            client.delete().forPath(PATH + "/child_2/2");
            System.out.println("二级节点 del...end");
            countDownLatch.countDown();
    
        }
    
        private static void addListener(final PathChildrenCache pathChildrenCache) {
            final PathChildrenCacheListener pathChildrenCacheListener = new PathChildrenCacheListener() {
                public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event) throws Exception {
                    System.out.println("listener child node path :" + event.getData().getPath() +
                        ", child node data: " + new String(event.getData().getData()));
                }
            };
            pathChildrenCache.getListenable().addListener(pathChildrenCacheListener);
        }
    
    }
    View Code

    控制台

    注意:上面输出 部分监听没有触发,应该是操作频繁,可以使用sleep间隔一下。

    有多个构造函数,并支持线程池回调

        public PathChildrenCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed, ThreadFactory threadFactory) {
            this(client, path, cacheData, dataIsCompressed, new CloseableExecutorService(Executors.newSingleThreadExecutor(threadFactory), true));
        }
    
        public PathChildrenCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed, ExecutorService executorService) {
            this(client, path, cacheData, dataIsCompressed, new CloseableExecutorService(executorService));
        }
    View Code

    2.3. TreeCache

    既能监听节点 也能监听子节点

    代码

    package com.rocky.learn.curator;
    
    import org.apache.curator.RetryPolicy;
    import org.apache.curator.framework.CuratorFramework;
    import org.apache.curator.framework.CuratorFrameworkFactory;
    import org.apache.curator.framework.recipes.cache.*;
    import org.apache.curator.retry.ExponentialBackoffRetry;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * @Author: rocky
     * @Date: Created in 2018/5/15.
     */
    public class TreeCacheTest {
        private static final String PATH = "/mytreecache/test";
        private static final String ADDRESS = "10.0.40.10:2181";
        private static TreeCache treeCache;
        private static CuratorFramework client;
        private static CountDownLatch countDownLatch = new CountDownLatch(1);
        static {
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            client = CuratorFrameworkFactory.builder()
                    .connectString(ADDRESS)
                    .sessionTimeoutMs(5000)
                    .connectionTimeoutMs(5000)
                    .retryPolicy(retryPolicy)
    //                .namespace(BASE)
                    .build();
            client.start();
        }
    
        public static void main(String[] args) throws Exception {
            startCache();
            countDownLatch.await();
        }
    
        private static void startCache() throws Exception {
            treeCache = new TreeCache(client, PATH);
            treeCache.start();
            addListener();
            for (int i = 1; i < 4; i++) {
                String newPath = PATH + "/child_" + i;
                String childNodeName = "child_" + i;
                client.create().creatingParentsIfNeeded().forPath(newPath, childNodeName.getBytes());
            }
            Thread.sleep(2000);
            client.setData().forPath(PATH, "change Papa Data first time".getBytes());
            Thread.sleep(2000);
            if(null != client.checkExists().forPath(PATH))
                client.setData().forPath(PATH + "/child_1", "change son Data first time".getBytes());
            Thread.sleep(2000);
            client.setData().forPath(PATH, "change Papa Data second time".getBytes());
            Thread.sleep(2000);
            countDownLatch.countDown();
    
        }
    
        private static void addListener() {
            treeCache.getListenable().addListener(new TreeCacheListener() {
                public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
                    System.out.println("node change...data>>" + new String(treeCacheEvent.getData().getData()));
                }
            });
        }
    
    }
    View Code

    控制台

    只要节点发生变化,监听事件就回执行回调,不论父节点还是子节点,且不用反复注册。

    2.4 ConnectionStateListener

    代码

            client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
                public void stateChanged(CuratorFramework curatorFramework, ConnectionState state) {
                    if(state == ConnectionState.CONNECTED){
                        System.out.println("zk connected..");
                    }else if(state == ConnectionState.LOST){
                        System.out.println("zk session lost..");
                    }else if(state == ConnectionState.RECONNECTED){
                        System.out.println("zk reconnected..");
                    }
                }
            });
    View Code

    ConnectionStateListener监控连接的状态,当连接状态为LOST,curator-recipes下的所有Api将会失效或者过期

    2.5 close

    用完后最好关闭 cache和 client(CuratorFramework)

    cache.close(); client.close()

  • 相关阅读:
    新克隆环境无法创建供应商,报供应商名称已存在
    批处理学习:for语句详解【经典】(转)
    信号与槽引用传递
    串口封装
    tcp客户端封装
    qt无法定位程序输入点 于动态链接库 qt5core.dll
    对象new和不new的理解
    Qt重绘机制
    红绿灯
    获取所有子控件
  • 原文地址:https://www.cnblogs.com/rocky-fang/p/9037509.html
Copyright © 2020-2023  润新知