前言
- 上篇文章小编利用原生zookeeper简单的封装了一些CRUD的方法,紧接着这篇文章介绍Watch机制的原理。
监控节点创建
public static void main(String[] args) throws Exception {
// 建立watcher
ZooKeeperWatcher zkWatch = new ZooKeeperWatcher();
// 创建连接
zkWatch.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);
zkWatch.createPath(PARENT_PATH, System.currentTimeMillis() +"", true); //true是传入的参数 代表监控节点的创建。
Thread.sleep(1000);
zkWatch.releaseConnection();
}
监控节点的更新
// 建立watcher
ZooKeeperWatcher zkWatch = new ZooKeeperWatcher();
// 创建连接
zkWatch.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);
//提前注册监控
zkWatch.readData(PARENT_PATH, true);
//更新父节点
zkWatch.writeData(PARENT_PATH, System.currentTimeMillis() +"");
Thread.sleep(1000);
zkWatch.releaseConnection();
监控节点的删除
// 建立watcher
ZooKeeperWatcher zkWatch = new ZooKeeperWatcher();
// 创建连接
zkWatch.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);
//提前注册监控
zkWatch.readData(PARENT_PATH, true);
//删除节点
zkWatch.deleteNode(PARENT_PATH);
Thread.sleep(1000);
//释放链接
zkWatch.releaseConnection();
监控子节点的创建
// 建立watcher
ZooKeeperWatcher zkWatch = new ZooKeeperWatcher();
// 创建连接
zkWatch.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);
//提前注册监控
//设置监控
zkWatch.getChildren(PARENT_PATH, true);
// 创建子节点
zkWatch.createPath(CHILDREN_PATH, System.currentTimeMillis() + "",true);
Thread.sleep(1000);
//释放链接
zkWatch.releaseConnection();
- 注意:这里监控的仍是父节点,其
EventType为NodeChildrenChanged
也就是说,无论是删除子节点,还是创建子节点,其EventType总是NodeChildrenChanged
。 - -
原生API的缺点
一次性监控:从原生的API中我们可以看出,由于Watch事件具有one-time trigger(一次性触发)的特性,所以我们每次操控节点时(增删改)都要提前注册监控,这是原生API的缺陷。
不返回数据:当我们对节点(增删改)操作完成之后,需要我们自己封装方法去读取更改后的内容,原生的API并不提供,这有点不符合我们的编程习惯。
- 不提供递归创建和递归删除:原生的API不提供递归创建节点和递归删除节点,也就是说,当我们创建子节点时,父节点必须存在,当我们删除节点时,该节点必须是子节点,若其父节点存在,会throw Exception。
小结
后来,zkClient 和 Curator 问世,这两个框架是对原生zookeeperAPI的再次封装,尤其是Curator提供Java客户端对Zookeeper的操作更人性化,不但提供分布式事务锁,还将上面的三个原生Zookeeper缺点全部补充,真是爽哉!