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()

 

posted @ 2018-05-16 14:27  fangfan  阅读(410)  评论(0编辑  收藏  举报