一、ZooKeeper类
Java语言版本的ZooKeeper主要通过org.apache.zookeeper.ZooKeeper这个类使用ZooKeeper服务。
ZooKeeper(connectString, sessionTimeout, watcher)
1. connectString: 使用逗号分隔的列表,每个ZooKeeper节点是一个host:ip对,host是机器名或者IP地址,port是ZooKeeper节点对客户端提供服务的端口号,客户端会任意选取connectString中的一个节点建立连接;
2. sessionTimeout: [session](https://juejin.cn/post/6844904145955078152#heading-12) timeout时间;
3. watcher: 用于接收来自ZooKeeper集群的事件。
栗子:
{
private String connectString = "localhost:2181";
private static int sessionTimeout = 2000;
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
List<String> children = null;
try {
children = zkClient.getChildren("/", true);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
二、ZooKeeper主要方法
- create(path, data, acl, flags):
在一个给定路径创建znode,并在znode保存data[]的数据,flag指定znode的类型;
zkClient.create("/data", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
- delete(path, version):
如果给定path上的znode的版本和给定的version匹配,删除znode; - exists(path, watch):
判断给定path上的znode是否存在,并在znode设置一个watch; - getData(path, watch):
返回给定path上的znode数据,并在znode设置一个watch; - setData(path, data, version):
如果给定path上的znode的版本和给定的version匹配,就设置znode数据; - getChildren(path, watch):
返回给定path上的znode数据,并在znode设置一个watch; - sync(path):
把客户端session连接节点和leader节点进行同步。
2.1方法说明
- 所有读取znode数据的API都可以设置一个watch用来监控znode的变化;
- 所有更新znode数据的API都有两个版本:无条件更新版本和条件更新版本。当version为-1,为无条件更新。否则只有指定的version和znode当前的version一致,才会进行更新,这样的更新是条件更新;
- 所有的方法都有同步和异步两个版本。同步版本的方法发送请求给ZooKeeper并等待服务器的响应。异步版本把请求放入客户端的请求队列,然后马上返回。异步版本通过callback来接受来自服务端的响应。
2.2 数据读取API-getData栗子
getData(String path, boolean watch, Stat stat)
同步方法。如果watch为true,该znode的状态变化会发送给构建ZooKeeper时指定的watcher。
getData(final String path, Watcher watcher,
DataCallback cb, Object ctx)
异步方法。watcher用来接收该znode的状态变化。
getData(String path, boolean watch, DataCallback cb, Object ctx)
异步方法。cb是一个callback,用来接收服务端的响应。ctx是提供给cb的context。如果watch为true,该znode的状态变化会发送给构建ZooKeeper时指定的watcher。
2.3 数据写入API-栗子
setData(final String path, byte data[], int version)
同步版本。如果version=-1,做无条件更新。如果version是非负整数,做条件更新。
setData(final String path, byte data[], int version,
StatCallback cb, Object ctx)
异步版本。
2.3 watch
watch提供一个让客户端获取最新数据的机制。如果没有watch机制,客户端需要不断的轮询ZooKeeper来查看是否有数据更新,这在分布式环境中是非常耗时的。客户端可以在读取数据的时候设置一个watcher,这样在数据更新时,客户端就会收到通知
2.4 条件更新
- 客户端1把/data更新到版本1,实现/data的自增,如步骤1所示;
- 客户端2把/data更新到版本2,实现/data的自增,如步骤2所示;
- 客户端1不知道 /data已经被客户端2更新过了,还用过时的版本1去更新/data,此时更新失败(报错version No is not valid : /data)。假如客户端1使用的是无条件更新,/data就会更新为2,没有实现自增。
使用条件更新可以避免对数据基于过期的数据进行数据更新操作。
三、ZooKeeper代码异常处理
所有同步执行的API方法都有可能抛出以下两个异常:
- KeeperException:
表示ZooKeeper服务端出错。
KeeperException的子类ConnectionLossException表示客户端和当前连接的ZooKeeper节点断开了连接。网络分区和ZooKeeper节点失败都会导致这个异常出现。发生此异常的时机可能是在ZooKeeper节点处理客户端请求之前,也可能是在ZooKeeper处理客户端请求之后。当出现此异常之后,客户端会进行自动重新连接,但是我们必须要检查我们以前的客户端请求是否被成功执行。 - InterruptedException:
表示方法被中断了。
我们可以使用Thread.interrupt()来中断API的执行。