在 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 | 用于获取节点的子节点列表和状态 |
来源: https://www.cnblogs.com/codestory/p/11434221.html