在ZooKeeper中,所有的同步调用命令,都会有一个相应的异步调用方法。异步调用能在一个单独线程中同时提交更多的命令,也能在一定程度上简化代码实现。
1 异步create方法如创建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); }
异步调用与同步调用的两个主要区别:
异步调用没有返回值(void)
异步调用不抛出异常,异常情况都通过rc参数传递
2 部分rc代码定义回调函数的第一个参数 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