ZooKeeper之Java客户端API使用—创建节点。

        客户端可以通过ZooKeeper的API来创建一个数据节点,有如下两个接口:

  • String create(final String path, byte data[], List<ACL> acl, CreateMode createMode)
  • void create(final String path, byte data[], List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx)

        这两个接口分别以同步和异步方式创建节点,API方法的参数说明如下表所示。

参数名说明
path需要创建的数据节点的节点路径,例如,/zk-book/foo
data[]一个字节数组,是节点创建后的初始内容
acl节点的ACL策略
createMode节点类型,是一个枚举类型,通常有4种可选的节点类型
  • 持久(PERSISTENT)
  • 持久顺序(PERSISTENT_SEQUENTIAL)
  • 临时(EPHEMERAL)
  • 临时顺序(EPHEMERAL_SEQUENTIAL)
cb注册一个异步回调函数。开发人员需要实现StringCallback接口,主要是对下面这个方法的重写:
void processResult(int rc, String path, Object ctx, String name);
当服务端节点创建完毕后,ZooKeeper客户端就会自动调用这个方法,这样就可以处理相关的业务逻辑了
ctx用于传递一个对象,可以在回调方法执行的时候使用,通常是放一个上下文(Context)信息

        需要注意几点,无论是同步还是异步接口,ZooKeeper都不支持递归创建,即无法在父节点不存在的情况下创建一个子节点。另外,如果一个节点已经存在了,那么创建同名节点的时候,会抛出NodeExistsException异常。

        目前,ZooKeeper的节点内容只支持字节数组(byte[])类型,也就是说,ZooKeeper不负责为节点内容进行序列化,开发人员需要自己使用序列化工具将节点内容进行序列化和反序列化。对于字符串,可以简单地使用“string”.getBytes()生成一个字节数组;对于其他复杂对象,可以使用Hessian或是Kryo等专门的序列化工具来进行序列化。

        关于权限控制,如果你的应用场景没有太高的权限要求,那么可以不关注这个参数,只需要在acl参数中传入参数Ids.OPEN_ACL_UNSAFE,这就表明之后对这个节点的任何操作都不受权限控制。

使用同步API创建一个节点

// ZooKeeper API创建节点,使用同步(sync)接口

public class ZooKeeper_Create_API_Sync_Usage implements Watcher {

private static CountDownLatch connectedSemaphore = new CountDownLatch(1);

public static void main(String[] args) throws Exception {

ZooKeeper zookeeper = new ZooKeeper("domain1.book.zookeeper:2181" , 5000 ,new ZooKeeper_Create_API_Sync_Usage());

connectedSemaphore.await();

String path1 = zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);

System.out.println("Success create znode: " + path1);

String path2 = zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

System.out.println("Success create znode: " + path2);

}

public void process(WatchedEvent event) {

if (KeeperState.SyncConnected == event.getState()) {

connectedSemaphore.countDown();

}

}

}

        运行程序,输出结果如下:

        在上面这个程序片段中,使用了同步的节点创建接口:String create(final String path, byte data[], List<ACL> acl, CreateMode createMode)。在接口使用中,我们分别创建了两种类型的节点:临时节点和临时顺序节点。从返回的结果可以看出,如果创建了临时节点,那么API的返回值就是当时传入的path参数;如果创建了临时顺序节点,那么ZooKeeper会自动在节点后缀加上一个数字,并且在API接口的返回值中返回该数据节点的一个完整的节点路径。

使用异步API创建一个节点

// ZooKeeper API 创建节点,使用异步(async)接口

public class ZooKeeper_Create_API_Sync_Usage implements Watcher {

private static CountDownLatch connectedSemaphore = new CountDownLatch(1);

public static void main(String[] args) throws Exception {

ZooKeeper zookeeper = new ZooKeeper("domain1.book.zookeeper:2181" , 5000 ,new ZooKeeper_Create_API_ASync_Usage());

connectedSemaphore.await();

zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, new IStringCallback(), "I am context.");

zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, new IStringCallback(), "I am context.");

zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL, new IStringCallback(), "I am context.");

Thread.sleep(Integer.MAX_VALUE);

}

public void process(WatchedEvent event) {

if (KeeperState.SyncConnected == event.getState()) {

connectedSemaphore.countDown();

}

}

}

class IStringCallback implements AsyncCallback.StringCallback {

public void processResult(int rc, String path, Object ctx, String name) {

System.out.println("Create path result: [" + rc + ", " + path + ", " + ctx + ", real path name: " + name);

}

}

        运行程序,输出结果如下:

        从这个程序片段中可以看出,使用异步方式创建接口也很简单。用户仅仅需要实现AsyncCallback.StringCallback()接口即可。AsyncCallback包含了StatCallback、DataCallback、ACLCallback、ChildrenCallback、Children2Callback、StringCallback和VoidCallback七种不同的回调接口,用户可以在不同的异步接口中实现不同的接口。

        和同步接口方法最大的区别在于,节点的创建过程(包括网络通信和服务端的节点创建过程)是异步的。并且,在同步接口调用过程中,我们需要关注接口抛出异常的可能;但是在异步接口中,接口本身是不会抛出异常的,所有的异常都会在回调函数中通过Result Code(响应码)来体现。

        下面来重点看下回调方法:void processResult(int rc, String path, Object ctx, String name)。这个方法的几个参数主要如下表所示。

参数名说明
rcResult Code,服务端响应码。客户端可以从这个响应码中识别出API调用的结果,常见的响应码如下。
  • 0(Ok):接口调用成功。
  • -4(ConnectionLoss):客户端和服务端连接已断开。
  • -110(NodeExists):指定节点已存在。
  • -112(SessionExpired):会话已过期。
path接口调用时传入API的数据节点的节点路径参数值。
ctx接口调用时传入API的ctx参数值。
name实际在服务端创建的节点名。在上面代码中,第三次创建节点时,由于创建的节点类型是顺序节点,因此在服务端没有真正创建好顺序节点之前,客户端无法知道节点的完整节点路径。于是,在回调方法中,服务端会返回这个数据节点的完整节点路径。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值