【zookeeper】Apache curator实战 03 《三种监听器》

1. 基于watch实现监听

利用Watcher来对节点进行监听操作,但此监听操作只能监听一次,与原生API并无太大差异。如有典型业务场景需要使用可考虑,但一般情况不推荐使用。

下面是具体的使用demo:

public class CuratorWatchEvent {
    public static CuratorFramework build(){
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
                .connectString("172.30.241.205:2181")
                .namespace(ZKConstant.ZK_NAMESPACE)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                .build();
        curatorFramework.start();
        return curatorFramework;
    }

    public static void main(String[] args) throws Exception{
        String path = "/watchtest";
        CuratorFramework client  = CuratorWatchEvent.build();
        client.create().creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL)
                .forPath(path);
        build().getData().usingWatcher(new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("监听器watchedEvent:" + watchedEvent);
            }
        }).forPath(path);

        client.setData().forPath(path,"new content".getBytes());

        // 第二次变更节点数据
        client.setData().forPath(path,"second content".getBytes());
        client.close();
    }
}

2. Listener

也是一次性的监听操作,使用后就无法在继续监听了

package zookeeper.curator.watcher;

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.CuratorEvent;
import org.junit.Test;
import zookeeper.curator.CuratorBaseOperations;

@Slf4j
public class CuratorListenerTest extends CuratorBaseOperations{

    @Test
    public void testCuratorListener() throws Exception {

        CuratorFramework curatorFramework = getCuratorFramework();
        curatorFramework.getCuratorListenable().addListener((CuratorFramework client, CuratorEvent event)->{
            log.info(" things changed1: event: {},  {} ",event.getType().name(),event);
        });

        String path = "/test";
        createIfNeed(path);
        log.info("start to change data for path :{}" ,path);
        curatorFramework.setData().inBackground().forPath(path,"xxx1".getBytes());
        log.info("start to change data for path :{} again" ,path);
        curatorFramework.setData().inBackground().forPath(path,"xxx2".getBytes());
        curatorFramework.create().inBackground().forPath("/test456","test456".getBytes());
    }




}

3. 基于cache实现监听

cache是一种缓存机制,Cache事件监听可以理解为一个本地缓存视图与远程Zookeeper视图的对比过程。Cache提供了反复注册的功能。
curator支持的cache种类有3种

  • Path Cache
    Path Cache用来观察ZNode的子节点并缓存状态,如果ZNode的子节点被创建,更新或者删除,那么Path Cache会更新缓存,并且触发事件给注册的监听器。

    Path Cache是通过PathChildrenCache类来实现的,监听器注册是通过PathChildrenCacheListener。

  • Node Cache
    Node Cache用来观察ZNode自身,如果ZNode节点本身被创建,更新或者删除,那么Node Cache会更新缓存,并触发事件给注册的监听器。

    Node Cache是通过NodeCache类来实现的,监听器对应的接口为NodeCacheListener。

  • Tree Cache
    可以看做是上两种的合体,Tree Cache观察的是ZNode及子节点。

3.1 node cache:

NodeCache 对某一个节点进行监听:

public NodeCache(CuratorFramework client,
                         String path)
Parameters:
client - the client
path - path to cache

可以通过注册监听器来实现,对当前节点数据变化的处理

public void addListener(NodeCacheListener listener)
     Add a change listener
Parameters:
listener - the listener

完整示例:

package zookeeper.curator.cache;


import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.junit.Test;
import zookeeper.curator.CuratorStandaloneBase;

@Slf4j
public class NodeCacheTest extends CuratorStandaloneBase{

    public static final String NODE_CACHE="/node-cache";

    @Test
    public void testNodeCacheTest() throws Exception {

        CuratorFramework curatorFramework = getCuratorFramework();

        createIfNeed(NODE_CACHE);
        NodeCache nodeCache = new NodeCache(curatorFramework, NODE_CACHE);
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                log.info("{} path nodeChanged: ",NODE_CACHE);
                printNodeData();
            }
        });

        nodeCache.start();
    }


    public void printNodeData() throws Exception {
        CuratorFramework curatorFramework = getCuratorFramework();
        byte[] bytes = curatorFramework.getData().forPath(NODE_CACHE);
        log.info("data: {}",new String(bytes));
    }
}

3.2 path cache:

PathChildrenCache 会对子节点进行监听,但是不会对二级子节点进行监听:

public PathChildrenCache(CuratorFramework client,
                         String path,
                         boolean cacheData)
Parameters:
client - the client
path - path to watch
cacheData - if true, node contents are cached in addition to the stat

可以通过注册监听器来实现,对当前节点的子节点数据变化的处理:

public void addListener(PathChildrenCacheListener listener)
     Add a change listener
Parameters:
listener - the listener

完整示例:

package zookeeper.curator.cache;


import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
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.junit.Test;
import zookeeper.curator.CuratorBaseOperations;

@Slf4j
public class PathCacheTest extends CuratorBaseOperations{

    public static final String PATH="/path-cache";

    @Test
    public void testPathCache() throws Exception {

        CuratorFramework curatorFramework = getCuratorFramework();

        createIfNeed(PATH);
        PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework, PATH, true);


        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                log.info("event:  {}",event);
            }
        });

        // 如果设置为true则在首次启动时就会缓存节点内容到Cache中
        pathChildrenCache.start(true);
    }
}

3.3 tree cache:

TreeCache 使用一个内部类TreeNode来维护这个一个树结构。并将这个树结构与ZK节点进行了映射。所以TreeCache 可以监听当前节点下所有节点的事件。

public TreeCache(CuratorFramework client,
                         String path,
                         boolean cacheData)
Parameters:
client - the client
path - path to watch
cacheData - if true, node contents are cached in addition to the stat

可以通过注册监听器来实现,对当前节点的子节点,及递归子节点数据变化的处理:

public void addListener(TreeCacheListener listener)
     Add a change listener
Parameters:
listener - the listener

完整示例:

package zookeeper.curator.cache;

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.junit.Test;
import zookeeper.curator.CuratorBaseOperations;

import java.util.Map;

@Slf4j
public class TreeCacheTest extends CuratorBaseOperations{

    public static final String TREE_CACHE="/tree-path";

    @Test
    public void testTreeCache() throws Exception {
        CuratorFramework curatorFramework = getCuratorFramework();
        createIfNeed(TREE_CACHE);
        TreeCache treeCache = new TreeCache(curatorFramework, TREE_CACHE);
        treeCache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
                log.info(" tree cache: {}",event);

                Map<String, ChildData> currentChildren = treeCache.getCurrentChildren(TREE_CACHE);
                log.info("currentChildren: {}",currentChildren);
            }
        });
        treeCache.start();
    }
}

参考

《Curator之监听》
《zookeeper入门之Curator的使用之几种监听器的使用》

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值