ZooKeeper Watch Java API浅析exists

本文通过具体示例深入解析ZooKeeper中的Watch机制,特别是exists()方法的应用,展示如何监控节点变化,并讨论其监控特性。

 Watch是ZooKeeper中非常重要的一个机制,它可以监控ZooKeeper中节点的变化情况,告知客户端。下面,我们以代码为例来分析Watch在ZooKeeper中是如何实现的。ZooKeeper中一共由三种方法可以实现Watch,分别为getData、exists和getChildren,今天我们先来看下exists()方法:

        2、exists()

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: zhubo
 * Date: 2018-01-10
 * Time: 17:44
 */
public class ZooKeeper_Watch_Exists {

    public static void main(String[] args) throws Exception{

        ZooKeeper zk = null;

        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("开始连接ZooKeeper...");
        // 创建与ZooKeeper服务器的连接zk
        String address = "centos4:2181";
        int sessionTimeout = 3000;
        zk = new ZooKeeper(address, sessionTimeout, new Watcher() {
            // 监控所有被触发的事件
            @Override
            public void process(WatchedEvent event) {
                if (event.getType() == null || "".equals(event.getType())) {
                    return;
                }
                System.out.println("已经触发了" + event.getType() + "事件!");
            }
        });
        System.out.println("ZooKeeper连接创建成功!");

        Thread.sleep(1000L);
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");

        // 创建根目录节点
        // 路径为/tmp_root_path
        // 节点内容为字符串"我是根目录/tmp_root_path"
        // 创建模式为CreateMode.PERSISTENT
        System.out.println("开始创建根目录节点/tmp_root_path...");
        zk.create("/tmp_root_path", "我是根目录/tmp_root_path".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("根目录节点/tmp_root_path创建成功!");


        Thread.sleep(1000L);

        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");

        // 创建第一个子目录节点
        // 路径为/tmp_root_path/childPath1
        // 节点内容为字符串"我是第一个子目录/tmp_root_path/childPath1"
        // 创建模式为CreateMode.PERSISTENT
        System.out.println("开始创建第一个子目录节点/tmp_root_path/childPath1...");
        zk.create("/tmp_root_path/childPath1",
                "我是第一个子目录/tmp_root_path/childPath1".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("第一个子目录节点/tmp_root_path/childPath1创建成功!");
        Thread.sleep(1000L);
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");

        Thread.sleep(1000L);

        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");

        // 创建第二个子目录节点
        // 路径为/tmp_root_path/childPath2
        // 节点内容为字符串"我是第二个子目录/tmp_root_path/childPath2"
        // 创建模式为CreateMode.PERSISTENT
        System.out.println("开始创建第二个子目录节点/tmp_root_path/childPath2...");
        zk.create("/tmp_root_path/childPath2",
                "我是第二个子目录/tmp_root_path/childPath2".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("第二个子目录节点/tmp_root_path/childPath2创建成功!");

        Thread.sleep(1000L);

        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");

        // 修改第一个子目录节点/tmp_root_path/childPath1数据
        System.out.println("开始修改第一个子目录节点/tmp_root_path/childPath1数据...");
        zk.setData("/tmp_root_path/childPath1",
                "我是修改数据后的第一个子目录/tmp_root_path/childPath1".getBytes(), -1);
        System.out.println("修改第一个子目录节点/tmp_root_path/childPath1数据成功!");

        Thread.sleep(1000L);

        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");

        // 修改第二个子目录节点/tmp_root_path/childPath2数据
        System.out.println("开始修改第二个子目录节点/tmp_root_path/childPath2数据...");
        zk.setData("/tmp_root_path/childPath2",
                "我是修改数据后的第二个子目录/tmp_root_path/childPath2".getBytes(), -1);
        System.out.println("修改第二个子目录节点/tmp_root_path/childPath2数据成功!");

        Thread.sleep(1000L);


        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");

        // 获取根目录节点状态
        System.out.println("开始获取根目录节点状态...");
        System.out.println(zk.exists("/tmp_root_path", true));
        System.out.println("根目录节点状态获取成功");

        Thread.sleep(1000L);

        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        // 删除第一个子目录节点
        System.out.println("开始删除第一个子目录节点/tmp_root_path/childPath1...");
        zk.delete("/tmp_root_path/childPath1", -1);
        System.out.println("第一个子目录节点/tmp_root_path/childPath1删除成功!");
        Thread.sleep(1000L);


        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");

        // 删除第二个子目录节点
        System.out.println("开始删除第二个子目录节点/tmp_root_path/childPath2...");
        zk.delete("/tmp_root_path/childPath2", -1);
        System.out.println("第二个子目录节点/tmp_root_path/childPath2删除成功!");
        Thread.sleep(1000L);


        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");


        // 删除根目录节点
        System.out.println("开始删除根目录节点/tmp_root_path...");
        zk.delete("/tmp_root_path", -1);
        System.out.println("根目录节点/tmp_root_path删除成功!");

        Thread.sleep(1000L);

        System.out.println("...");
        System.out.println("...");
        System.out.println("...");
        System.out.println("...");


        zk.close();

    }
}
[2018-01-10 19:00:24.381  INFO org.apache.zookeeper.ZooKeeper:438] [main] Initiating client connection, connectString=centos4:2181 sessionTimeout=3000 watcher=com.timer.watch.ZooKeeper_Watch_Exists$1@17d99928
ZooKeeper连接创建成功!
[2018-01-10 19:00:24.502  INFO org.apache.zookeeper.ClientCnxn:1032] [main-SendThread(centos4:2181)] Opening socket connection to server centos4/192.168.20.244:2181. Will not attempt to authenticate using SASL (unknown error)
[2018-01-10 19:00:24.508  INFO org.apache.zookeeper.ClientCnxn:876] [main-SendThread(centos4:2181)] Socket connection established to centos4/192.168.20.244:2181, initiating session
[2018-01-10 19:00:24.527  INFO org.apache.zookeeper.ClientCnxn:1299] [main-SendThread(centos4:2181)] Session establishment complete on server centos4/192.168.20.244:2181, sessionid = 0x160db22da860054, negotiated timeout = 4000
已经触发了None事件!
...
...
...
...
开始创建根目录节点/tmp_root_path...
根目录节点/tmp_root_path创建成功!
...
...
...
...
开始创建第一个子目录节点/tmp_root_path/childPath1...
第一个子目录节点/tmp_root_path/childPath1创建成功!
...
...
...
...
...
...
...
...
开始创建第二个子目录节点/tmp_root_path/childPath2...
第二个子目录节点/tmp_root_path/childPath2创建成功!
...
...
...
...
开始修改第一个子目录节点/tmp_root_path/childPath1数据...
修改第一个子目录节点/tmp_root_path/childPath1数据成功!
...
...
...
...
开始修改第二个子目录节点/tmp_root_path/childPath2数据...
修改第二个子目录节点/tmp_root_path/childPath2数据成功!
...
...
...
...
开始获取根目录节点状态...
2299,2299,1515580941316,1515580941316,0,2,0,0,29,2,2301

根目录节点状态获取成功
...
...
...
...
开始删除第一个子目录节点/tmp_root_path/childPath1...
第一个子目录节点/tmp_root_path/childPath1删除成功!
...
...
...
...
开始删除第二个子目录节点/tmp_root_path/childPath2...
第二个子目录节点/tmp_root_path/childPath2删除成功!
...
...
...
...
开始删除根目录节点/tmp_root_path...
已经触发了NodeDeleted事件!
根目录节点/tmp_root_path删除成功!
...
...
...
...
[2018-01-10 19:00:35.624  INFO org.apache.zookeeper.ZooKeeper:684] [main] Session: 0x160db22da860054 closed

而如果我们在获取根目录节点状态之后,修改根目录数据,添加代码和执行结果如下:

// 修改根目录节点数据  
System.out.println("开始修改根目录节点/tmp_root_path数据...");  
zk.setData("/tmp_root_path",  
        "我是修改数据后的根目录/tmp_root_path".getBytes(), -1);  
System.out.println("修改根目录节点/tmp_root_path数据成功!");  
  
Thread.currentThread().sleep(1000l);  
  
System.out.println("...");  
System.out.println("...");  
System.out.println("...");  
System.out.println("...");
[2018-01-10 19:04:10.626  INFO org.apache.zookeeper.ZooKeeper:438] [main] Initiating client connection, connectString=centos4:2181 sessionTimeout=3000 watcher=com.timer.watch.ZooKeeper_Watch_Exists$1@17d99928
ZooKeeper连接创建成功!
[2018-01-10 19:04:10.778  INFO org.apache.zookeeper.ClientCnxn:1032] [main-SendThread(centos4:2181)] Opening socket connection to server centos4/192.168.20.244:2181. Will not attempt to authenticate using SASL (unknown error)
[2018-01-10 19:04:10.782  INFO org.apache.zookeeper.ClientCnxn:876] [main-SendThread(centos4:2181)] Socket connection established to centos4/192.168.20.244:2181, initiating session
[2018-01-10 19:04:10.801  INFO org.apache.zookeeper.ClientCnxn:1299] [main-SendThread(centos4:2181)] Session establishment complete on server centos4/192.168.20.244:2181, sessionid = 0x160db22da860055, negotiated timeout = 4000
已经触发了None事件!
...
...
...
...
开始创建根目录节点/tmp_root_path...
根目录节点/tmp_root_path创建成功!
...
...
...
...
开始创建第一个子目录节点/tmp_root_path/childPath1...
第一个子目录节点/tmp_root_path/childPath1创建成功!
...
...
...
...
...
...
...
...
开始创建第二个子目录节点/tmp_root_path/childPath2...
第二个子目录节点/tmp_root_path/childPath2创建成功!
...
...
...
...
开始修改第一个子目录节点/tmp_root_path/childPath1数据...
修改第一个子目录节点/tmp_root_path/childPath1数据成功!
...
...
...
...
开始修改第二个子目录节点/tmp_root_path/childPath2数据...
修改第二个子目录节点/tmp_root_path/childPath2数据成功!
...
...
...
...
开始获取根目录节点状态...
2309,2309,1515581167602,1515581167602,0,2,0,0,29,2,2311

根目录节点状态获取成功
...
...
...
...
开始删除第一个子目录节点/tmp_root_path/childPath1...
第一个子目录节点/tmp_root_path/childPath1删除成功!
...
...
...
...
开始删除第二个子目录节点/tmp_root_path/childPath2...
第二个子目录节点/tmp_root_path/childPath2删除成功!
...
...
...
...
开始修改根目录节点/tmp_root_path数据...
已经触发了NodeDataChanged事件!
修改根目录节点/tmp_root_path数据成功!
...
...
...
...
开始删除根目录节点/tmp_root_path...
根目录节点/tmp_root_path删除成功!
...
...
...
...
[2018-01-10 19:04:22.894  INFO org.apache.zookeeper.ZooKeeper:684] [main] Session: 0x160db22da860055 closed

与getData()一致!

 结论:
        exists()方法仅仅监控对应节点的一次数据变化,无论是数据修改还是删除!若要每次对应节点发生变化都被监测到,那么每次都得先调用exists()方法获取一遍节点状态!

 

 

 

 

 

转载于:https://my.oschina.net/LucasZhu/blog/1605292

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值