Curator Framework操作zookeeper(1)-基本操作

1  maven依賴

<zookeeper.version>3.4.11</zookeeper.version>
<apache.curator.version>4.1.0</apache.curator.version>
<!-- zookeeper -->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>${zookeeper.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- apache.curator zookeeper -->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>${apache.curator.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>${apache.curator.version}</version>
    <exclusions>
        <exclusion>
            <artifactId>slf4j-api</artifactId>
            <groupId>org.slf4j</groupId>
        </exclusion>
        <exclusion>
            <artifactId>zookeeper</artifactId>
            <groupId>org.apache.zookeeper</groupId>
        </exclusion>
    </exclusions>
</dependency>

2 工具類

import cn.sun.curator.listener.AbstractNodeCacheListener;
import cn.sun.curator.listener.SessionConnectionStateListener;
import cn.sun.util.PropertiesUtil;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.ACLBackgroundPathAndBytesable;
import org.apache.curator.framework.api.BackgroundPathAndBytesable;
import org.apache.curator.framework.api.BackgroundPathable;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Properties;

/**
 * zk工具類
 */
public class ZkUtil {
    private static final Logger log = LoggerFactory.getLogger(ZkUtil.class);
    public static String NAMESPACE = "chy";
    public static Properties pu = PropertiesUtil.loadProperties("classpath:zkconfig.properties");
    public static CuratorFramework client;
    public static String env = "DEV";

    public static synchronized void initialize() {
        String zkhost = null;
        int sessionTimeout = 60000;
        int connTimeout = 3000;
        try {
            log.info("read classpath:zkconfig.properties, env: " + env);
            if (pu != null) {
                zkhost = pu.getProperty(env + "_ZK_SERVER");
                sessionTimeout = Integer.valueOf(pu.getProperty("sessionTimeout", "60000")).intValue();
                connTimeout = Integer.valueOf(pu.getProperty("connTimeout", "3000")).intValue();
                client = createClient(zkhost, sessionTimeout, connTimeout, NAMESPACE);
            }
        } catch (Exception e) {
            log.error("init zkUtil error!", e);
        }
    }

    public static CuratorFramework createClient(String zkhost, int sessionTimeout, int connTimeout, String nameSpace) {
        CuratorFramework client = null;
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder().connectString(zkhost)
                .sessionTimeoutMs(sessionTimeout)
                .connectionTimeoutMs(connTimeout)
                .canBeReadOnly(false)
                .retryPolicy(retryPolicy)
                //會在路徑前面補齊  /zkconfig/node ----> /nameSpace/zkconfig/node
                .namespace(nameSpace)
                .defaultData(null).build();
        client.getConnectionStateListenable().addListener(new SessionConnectionStateListener());
        client.start();
        return client;
    }

    /**
     * 判斷節點是否存在
     * @param path
     * @return
     */
    public static boolean checkExist(String path) {
        try {
            if (client.checkExists().forPath(path) == null) {
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error("checkExist error! path: " + path, e);
        }
        return false;
    }

    /**
     * 判斷節點是否存在並監聽節點
     * @param path
     * @param watcher
     * @return
     */
    public static boolean checkExist(String path,Watcher watcher) {
        try {
            if (client.checkExists().usingWatcher(watcher).forPath(path) == null) {
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error("checkExist error! path: " + path, e);
        }
        return false;
    }

    /**
     * 獲取存在的節點數據並監聽節點變更
     * @param path
     * @param watcher
     * @return
     */
    public static String getData(String path, Watcher watcher) {
        byte[] data = null;
        String res = null;
        try {
            data = (byte[]) ((BackgroundPathable) client.getData().usingWatcher(watcher)).forPath(path);
            res = new String(data, "utf-8");
        } catch (Exception e) {
            log.error("get data error! path: " + path, e);
        }
        return res;
    }

    /**
     * 獲取節點數據
     * @param path
     * @return
     */
    public static String getData(String path) {
        byte[] data = null;
        String res = null;
        try {
            data = (byte[]) client.getData().forPath(path);
            res = new String(data, "utf-8");
        } catch (Exception e) {
            log.error("get data error! path: " + path, e);
        }
        return res;
    }

    /* 分佈式隊列
    public static SimpleDistributedQueue createDisQueue(CuratorFramework client, String taskName, String name) {
        SimpleDistributedQueue queue = new SimpleDistributedQueue(client, ROOT_TASK + "/" + taskName + "/" + name);
        return queue;
    }
    */

    /**
     * 創建持久節點
     * @param path
     * @return
     */
    public static boolean create(String path)  {
        return create(path, "");
    }

    /**
     * 創建持久節點和數據
     * @param path
     * @param data
     * @return
     */
    public static boolean create(String path, String data) {
        try {
            ((BackgroundPathAndBytesable) ((ACLBackgroundPathAndBytesable) client.create().creatingParentsIfNeeded()
                    .withMode(CreateMode.PERSISTENT)).
                    withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE))
                    .forPath(path, data.getBytes("utf-8"));
            return true;
        } catch (Exception e) {
            log.error("創建Zookeeper節點出現異常,nodePath:{0}", path, e);
        }
        return false;
    }

    /**
     * 增加節點
     * @param path
     * @param childNode
     * @return
     */
    public static boolean addNode(String path, String childNode)  {
        return !checkExist(path + "/" + childNode) ? create( path + "/" + childNode) : true;
    }

    /**
     * 增加節點
     * @param path
     * @param childNode
     * @param data
     * @return
     */
    public static boolean addNode(String path, String childNode, String data)  {
        if (data == null) {
            data = "";
        }
        return !checkExist( path + "/" + childNode) ? create( path + "/" + childNode, data) : true;
    }

    /**
     * 刪除某個子節點
     * @param path
     * @param childNode
     * @return
     * @throws Exception
     */
    public static boolean deleteNode(String path, String childNode)  {
        return checkExist( path + "/" + childNode) ? deleteChildrenIfNeeded( path + "/" + childNode) : true;
    }

    /**
     * 級聯刪除某個Zookeeper節點及其子節點
     * @param path
     * @return
     * @throws Exception
     */
    public static boolean deleteChildrenIfNeeded(String path) {
        try {
            client.delete().deletingChildrenIfNeeded().forPath(path);
            return true;
        } catch (Exception e) {
            log.error("刪除Zookeeper節點出現異常,nodePath:{}", path, e);
        }
        return false;
    }

    /**
     * 新增持久節點或者更新節點數據
     * @param path
     * @param data
     * @throws Exception
     */
    public static void createOrUpdateNode(String path, String data)  {
        try {
            if (!checkExist(path)) {
                ((BackgroundPathAndBytesable)((ACLBackgroundPathAndBytesable)client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT)).withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)).forPath(path, data.getBytes("utf-8"));
            } else {
                client.setData().forPath(path, data.getBytes("utf-8"));
            }
        } catch (Exception e) {
            log.error("創建或更新Zookeeper節點出現異常,nodePath:{}", path, e);
        }
    }

    /**
     * 更新節點數據
     * @param path
     * @param data
     * @throws Exception
     */
    public static void updateNodeData(String path, String data)  {
        try {
            client.setData().forPath(path, data.getBytes("utf-8"));
        } catch (Exception e) {
            log.error("更新Zookeeper節點出現異常,nodePath:{}", path, e);
        }
    }

    /**
     * 創建永久Zookeeper節點
     * @param nodePath 節點路徑(如果父節點不存在則會自動創建父節點),如:/curator
     * @param nodeValue 節點數據
     * @return java.lang.String 返回創建成功的節點路徑
     */
    public static String createPersistentNode(String nodePath, String nodeValue){
        try {
            return client.create().creatingParentsIfNeeded()
                    .forPath(nodePath,nodeValue.getBytes("utf-8"));
        } catch (Exception e) {
            log.error("創建永久Zookeeper節點失敗,nodePath:{},nodeValue:{}",nodePath,nodeValue,e);
        }
        return null;
    }

    /**
     * 創建永久有序Zookeeper節點
     * @param nodePath 節點路徑(如果父節點不存在則會自動創建父節點),如:/curator
     * @param nodeValue 節點數據
     * @return java.lang.String 返回創建成功的節點路徑
     */
    public static String createSequentialPersistentNode(String nodePath, String nodeValue){
        try {
            return client.create().creatingParentsIfNeeded()
                    .withMode(CreateMode.PERSISTENT_SEQUENTIAL)
                    .forPath(nodePath,nodeValue.getBytes("utf-8"));
        } catch (Exception e) {
            log.error("創建永久有序Zookeeper節點失敗,nodePath:{},nodeValue:{}",nodePath,nodeValue,e);
        }
        return null;
    }


    /**
     * 創建臨時Zookeeper節點
     * @param nodePath 節點路徑(如果父節點不存在則會自動創建父節點),如:/curator
     * @param nodeValue 節點數據
     * @return java.lang.String 返回創建成功的節點路徑
     */
    public static String createEphemeralNode(String nodePath, String nodeValue){
        try {
            return client.create().creatingParentsIfNeeded()
                    .withMode(CreateMode.EPHEMERAL)
                    .forPath(nodePath,nodeValue.getBytes("utf-8"));
        } catch (Exception e) {
            log.error("創建臨時Zookeeper節點失敗,nodePath:{},nodeValue:{}",nodePath,nodeValue,e);
        }
        return null;
    }

    /**
     * 創建臨時有序Zookeeper節點
     * @param nodePath 節點路徑(如果父節點不存在則會自動創建父節點),如:/curator
     * @param nodeValue 節點數據
     * @return java.lang.String 返回創建成功的節點路徑
     */
    public static String createSequentialEphemeralNode(String nodePath, String nodeValue){
        try {
            return client.create().creatingParentsIfNeeded()
                    .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                    .forPath(nodePath,nodeValue.getBytes("utf-8"));
        } catch (Exception e) {
            log.error("創建臨時有序Zookeeper節點失敗,nodePath:{},nodeValue:{}",nodePath,nodeValue,e);
        }
        return null;
    }

    /**
     * 獲取某個Zookeeper節點的所有子節點
     * @param nodePath 節點路徑
     * @return java.util.List<java.lang.String> 返回所有子節點的節點名
     */
    public static List<String> getChildren(String nodePath){
        try {
            return client.getChildren().forPath(nodePath);
        } catch (Exception e) {
            log.error("獲取某個Zookeeper節點的所有子節點出現異常,nodePath:{}",nodePath,e);
        }
        return null;
    }

    /**
     * 註冊節點監聽器
     * NodeCache: 對一個節點進行監聽,監聽事件包括指定路徑的增刪改操作
     * @param nodePath 節點路徑
     * @param listener 監控事件的回調接口
     * @return void
     */
    public static NodeCache registerNodeCacheListener(String nodePath,AbstractNodeCacheListener listener){
        try {
            //1. 創建一個NodeCache
            NodeCache nodeCache = new NodeCache(client, nodePath);

            //2. 緩存NodeCache
            listener.setNodeCache(nodeCache);

            //3. 添加節點監聽器
            nodeCache.getListenable().addListener(listener);

            //4. 啓動監聽器
            nodeCache.start();

            //5. 返回NodeCache
            return nodeCache;
        } catch (Exception e) {
            log.error("註冊節點監聽器出現異常,nodePath:{}",nodePath,e);
        }
        return null;
    }

    /**
     * 註冊目錄中子目錄監聽器
     * PathChildrenCache:對指定路徑節點的一級子目錄監聽,不對該節點的操作監聽,對其子目錄的增刪改操作監聽
     * 備註: 當節點存在時,添加監聽事件後會觸發 NODE_ADDED
     * @param nodePath 節點路徑
     * @param listener 監控事件的回調接口
     * @return org.apache.curator.framework.recipes.cache.PathChildrenCache
     */
    public static PathChildrenCache registerPathChildListener(String nodePath, PathChildrenCacheListener listener){
        try {
            //1. 創建一個PathChildrenCache
            PathChildrenCache pathChildrenCache = new PathChildrenCache(client, nodePath, true);

            //2. 添加目錄監聽器
            pathChildrenCache.getListenable().addListener(listener);

            //3. 啓動監聽器
            pathChildrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);

            //4. 返回PathChildrenCache
            return pathChildrenCache;
        } catch (Exception e) {
            log.error("註冊子目錄監聽器出現異常,nodePath:{}",nodePath,e);
        }
        return null;
    }

    /**
     * 註冊目錄監聽器
     * TreeCache:綜合NodeCache和PathChildrenCahce的特性,可以對整個目錄進行監聽,同時還可以設置監聽深度
     * 備註: 當節點存在時,添加監聽事件後會觸發 NODE_ADDED
     * @param nodePath 節點路徑
     * @param maxDepth 自定義監控深度
     * @param listener 監控事件的回調接口
     * @return org.apache.curator.framework.recipes.cache.TreeCache
     */
    public static TreeCache registerTreeCacheListener(String nodePath, int maxDepth, TreeCacheListener listener){
        try {
            //1. 創建一個TreeCache
            TreeCache treeCache = TreeCache.newBuilder(client, nodePath)
                    .setCacheData(true)
                    .setMaxDepth(maxDepth)
                    .build();

            //2. 添加目錄監聽器
            treeCache.getListenable().addListener(listener);

            //3. 啓動監聽器
            treeCache.start();

            //4. 返回TreeCache
            return treeCache;
        } catch (Exception e) {
            log.error("註冊目錄監聽器出現異常,nodePath:{},maxDepth:{}",nodePath,e);
        }
        return null;
    }
}

 

4 zkconfig.properties

DEV_ZK_SERVER=127.0.0.1
PRD_ZK_SERVER=127.0.0.1

5 測試代碼

public static void testCreate(){
        ZkUtil.initialize();
        String parent = "/zkconfig";
        String child = "chynode";
        String path = parent + "/" + child;
        NodeWatcher nodeWatcher = new NodeWatcher(ZkUtil.client, path);

        //開啓監聽
        ZkUtil.checkExist("/zkconfig/chynode", nodeWatcher);

        //如果不存在節點增加節點
        try {
            if (!ZkUtil.checkExist(path)) {
                ZkUtil.addNode(parent, child, "chy");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //如果存在節點獲取節點信息
        if (ZkUtil.checkExist(path)) {
            log.info("{}:{}", path, ZkUtil.getData("/zkconfig/chynode"));
        }
    }

    public static void testDelete(){
        ZkUtil.initialize();
        String parent = "/zkconfig";
        String child = "chynode";
        String path = parent + "/" + child;
        NodeWatcher nodeWatcher = new NodeWatcher(ZkUtil.client, path);

        //如果不存在節點增加節點
        try {
            if (!ZkUtil.checkExist(path)) {
                ZkUtil.addNode(parent, child, "chy");
                ZkUtil.addNode(parent, "chytemp", "chy");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        List<String> paths = ZkUtil.getChildren(parent);

        log.info("paths:{}", JSONObject.toJSONString(paths));

        //刪除子節點
        ZkUtil.deleteNode(parent, child);

        paths = ZkUtil.getChildren(parent);

        log.info("paths:{}", JSONObject.toJSONString(paths));

        //刪除當前節點以及子節點
        ZkUtil.deleteChildrenIfNeeded(parent);

        paths = ZkUtil.getChildren(parent);

        log.info("paths:{}", JSONObject.toJSONString(paths));

    }
    

    public static void testSequentialEphemeralNode(){
        ZkUtil.initialize();
        String parent = "/zkconfig";
        String child = "chynode";
        String path = parent + "/" + child;

        ZkUtil.deleteChildrenIfNeeded(parent);

        log.info(ZkUtil.createSequentialEphemeralNode(path,"001"));
        log.info(ZkUtil.createSequentialEphemeralNode(path,"002"));
        log.info(ZkUtil.createSequentialEphemeralNode(path,"003"));

        List<String> paths = ZkUtil.getChildren(parent);

        log.info("paths:{}", JSONObject.toJSONString(paths));
    }

    public static void testSequentialPersistentNode(){
        ZkUtil.initialize();
        String parent = "/zkconfig";
        String child = "chynode";
        String path = parent + "/" + child;

        ZkUtil.deleteChildrenIfNeeded(parent);

        log.info(ZkUtil.createSequentialPersistentNode(path,"001"));
        log.info(ZkUtil.createSequentialPersistentNode(path,"002"));
        log.info(ZkUtil.createSequentialPersistentNode(path,"003"));

        List<String> paths = ZkUtil.getChildren(parent);

        log.info("paths:{}", JSONObject.toJSONString(paths));
    }

    public static void testPersistentNode(){
        ZkUtil.initialize();
        String parent = "/zkconfig";
        String child = "chynode";
        String path = parent + "/" + child;

        ZkUtil.deleteChildrenIfNeeded(parent);

        log.info(ZkUtil.createEphemeralNode(path,"001"));

        List<String> paths = ZkUtil.getChildren(parent);

        log.info("paths:{}", JSONObject.toJSONString(paths));
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章