在ZooKeeper中,所有的同步调用命令,都会有一个相应的异步调用方法。异步调用能在一个单独线程中同时提交更多的命令,也能在一定程度上简化代码实现。
如创建zNode的命令create,同步方法的定义是
/**
* @param path 创建节点的路径
* @param data 创建节点的初始值
* @param acl 创建节点的ACL
* @param createMode 创建节点使用永久还是临时模式
* @return 创建节点的真实路径
* @throws KeeperException 服务器返回了非0的错误代码
* @throws KeeperException.InvalidACLException ACL非法或者为空
* @throws InterruptedException 事务被中断
* @throws IllegalArgumentException 路径非法
*/
public String create(final String path,
byte data[],
List<ACL> acl,
CreateMode createMode);
对应的异步调用方法
/**
* create方法的异步调用方法
* @param path 创建节点的路径
* @param data 创建节点的初始值
* @param acl 创建节点的ACL
* @param createMode 创建节点使用永久还是临时模式
* @param cb 包括回调函数的对象
* @param ctx 上下文对象(异步回调时会传递给callback,方便出错时重新调用)
*/
public void create(final String path,
byte data[],
List<ACL> acl,
CreateMode createMode,
StringCallback cb,
Object ctx);
StringCallback的定义
interface StringCallback extends AsyncCallback {
/**
* 处理异步调用的结果
* @param rc 调用的返回码
* @param path 异步调用时的路径参数
* @param ctx 异步调用时的上下文对象
* @param name 实际创建的节点名
* 成功时通常同path相同,除非创建的是sequential节点
*/
public void processResult(int rc,
String path,
Object ctx,
String name);
}
异步调用与同步调用的两个主要区别:
回调函数的第一个参数 rc ,是调用的返回值。ZooKeeper在枚举org.apache.zookeeper.KeeperException.Code中做了定义。从源码中摘出一些我们可能会经常使用的Code
/** 一切安好 */
OK (Ok),
/** 服务器连接丢失 */
CONNECTIONLOSS (ConnectionLoss),
/** 操作超时 */
OPERATIONTIMEOUT (OperationTimeout),
/** 参数错误 */
BADARGUMENTS (BadArguments),
/** 节点不存在 */
NONODE (NoNode),
/** 临时节点没有子节点 */
NOCHILDRENFOREPHEMERALS (NoChildrenForEphemerals),
/** 节点已经存在 */
NODEEXISTS (NodeExists),
/** 节点有子节点 */
NOTEMPTY (NotEmpty),
/** 会话超时 */
SESSIONEXPIRED (SessionExpired),
/** 请求超时*/
REQUESTTIMEOUT (-122),
3 回调函数的一般用法
下面是一个创建节点的简单例子。注意,ctx参数传递的是data,这个参数会直接传递到callback函数中,这样就可以直接重新调用create命令。
void createNode(String path, byte[] data) {
zooKeeper.create(nodePath, data,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL,
nodeCreateCallback,
data);
}
AsyncCallback.StringCallback nodeCreateCallback = new AsyncCallback.StringCallback() {
public void processResult(int rc, String path, Object ctx, String name) {
switch (KeeperException.Code.get(rc)) {
case OK:
// 创建节点成功
break;
case CONNECTIONLOSS:
// 连接丢失,重新发布命令
createNode(path, ctx);
return;
default:
// 其他异常,抛出或记录异常
KeeperException e = KeeperException.create(KeeperException.Code.get(rc), path);
log.error("create node error", e);
}
}
};
4 异步回调接口定义
ZooKeeper在org.apache.zookeeper.AsyncCallback中定义了几个回调接口
回调接口 | 说明 | 适用的异步命令 |
---|---|---|
StatCallback | 用于获取节点的状态 | void exists()void setData() |
DataCallback | 用于获取节点的值和状态 | void getData()void getConfig() |
ACLCallback | 用于获取节点的ACL信息和状态 | void getACL() |
ChildrenCallback | 用于获取节点的子节点列表 | void getChildren() |
Children2Callback | 用于获取节点的子节点列表和状态 | void getChildren() |
Create2Callback | 用于获取节点的名称和状态 | void create() |
StringCallback | 用于获取节点的名称 | void create() |
VoidCallback | 不返回任何信息 | void delete()void sync()void removeWatches()void removeAllWatches() |
MultiCallback | 用于多命令请求的返回值 | void multi() |
可以看到,有些异步命令,可以选择使用多个不同的Callback,见下表
异步命令 | 可选的回调接口 | 接口说明 |
---|---|---|
void create() | Create2Callback | 用于获取节点的名称和状态 |
StringCallback | 用于获取节点的名称 | |
void getChildren() | ChildrenCallback | 用于获取节点的子节点列表 |
Children2Callback | 用于获取节点的子节点列表和状态 |