为了完成本关任务,你需要掌握: 1.同步调用和异步调用区别; 2.节点创建 API 使用; 3.节点删除 API 使用。
同步调用和异步调用
ZooKeeper 提供的 API 操作有异步调用和同步调用两种,区别在于:
-
同步调用需要处理异常;
-
异步调用已经把异常封装为返回码。一般来说异步调用会在命令发送到 Zookeeper 服务器之前,就返回继续执行之后的代码。
推荐使用异步调用方法,不但可以获得更好的性能,更可以统一编码风格,免去对异常的处理。同时,即使方法调用失败,回调函数仍然会继续调用失败的方法,直到返回正确的返回码。
节点创建 API 的使用
节点创建 API 分为同步和异步创建两种方式:
一、 同步调用节点创建方法:
public String create(final String path, byte data[], List<ACL> acl, CreateMode createMode) throws KeeperException, InterruptedException
上述方法的参数含义如下所示:
1、path:创建节点的路径;
2、data[]:创建节点的数据值,参数类型是字节数组;
3、acl:节点的访问权限。主要有以下几种类型:
- ANYONE_ID_UNSAFE:任何人;
- AUTH_IDS:只用来授权;
- OPEN_ACL_UNSAFE:开放的 ACL;
- CREATOR_ALL_ACL:创建 ACL;
- READ_ACL_UNSAFE: 所有人可读。
4、createMode:节点类型。主要有以下几种类型:
- PERSISTENT:持久;
- PERSISTENT_SEQUENTIAL:持久顺序;
- EPHEMERAL:临时;
- EPHEMERAL_SEQUENTIAL:临时顺序。
同步创建临时节点示例:
String ephemeralPath = zooKeeper.create("/zk-test-create-ephemeral", "ephemeral".getBytes(), ZooDefs.Ids.ANYONE_ID_UNSAFE, CreateMode.EPHEMERAL);
上述语句可用于创建一个临时节点 /zk-test-create-ephemeral,节点数据为"ephemeral",该节点的访问权限为任何人。
二、异步调用节点创建方法:
public void create(final String path, byte data[], List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx)
同步创建方法的参数异步方法都有,除此之外,它还有以下两个特有的:
- cb:回调函数对象,该对象需实现回调函数接口,并重写 processResult() 方法。数据节点创建完成之后,会调用此方法进行业务逻辑处理;
- ctx:创建节点的名称。
异步创建临时顺序节点:
zooKeeper.create("/zk-test-create-async-sequential","async-sequential".getBytes(), ZooDefs.Ids.ANYONE_ID_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,new MyStringCallBack(),"CreateNode");
上述语句可用于创建一个临时顺序节点 /zk-test-create-async-sequential,节点数据为"async-sequential",节点的访问权限为任何人,节点上下文信息为“CreateNode”,节点的回调函数为我们自己创建的 MyStringCallBack 对象。
同步和异步节点创建示例:
import org.apache.zookeeper.*;
import java.io.IOException;
public class MyTest {
private ZooKeeper zk;
// 实现一个 Watcher
private Watcher wh = new Watcher() {
// 重写 process 方法
public void process(WatchedEvent event) {
System.out.println(event);
}
};
// 连接 ZooKeeper 服务器
public void createZKInstance() throws IOException {
zk = new ZooKeeper("localhost:2181", 15000, this.wh);
}
// 同步创建节点
public String createNode() throws IOException, KeeperException, InterruptedException {
String ephemeralPath = zk.create("/zk-test-create-ephemeral", "ephemeral".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
return ephemeralPath;
}
// 异步创建节点
public void createNodeSync() throws KeeperException, InterruptedException{
zk.create("/zk-test-create-async-sequential","async-sequential".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,new MyStringCallBack(),"CreateNode");
}
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
MyTest myTest = new MyTest();
// 连接 ZooKeeper 服务器
myTest.createZKInstance();
// 同步创建节点
String node = myTest.createNode();
// 输出节点
System.out.println(node);
// 异步创建节点
myTest.createNodeSync();
}
// 回调函数
public static class MyStringCallBack implements AsyncCallback.StringCallback{
@Override
public void processResult(int i, String s, Object o, String s1) {
System.out.println(s);
}
}
}
执行结果:
WatchedEvent state:SyncConnected type:None path:null
/zk-test-create-ephemeral
/zk-test-create-async-sequential
上述代码中,我们使用同步方法创建了节点 /zk-test-create-ephemeral,使用异步方法创建了节点 /zk-test-create-async-sequential。
节点删除API使用
同样的,节点删除也有异步和同步两种方法,分别使用以下 API :
同步删除:
zk.delete(String path, int version);
异步删除:
zk.delete(String path, int version, StringCallback cb, Object ctx);
其中,version 表示不同的版本,可以通过 Stat 对象的 getVersion() 方法获取。如果该值为 -1,则忽略版本,将节点删除。
删除之前创建的节点示例:
import org.apache.zookeeper.*;
import java.io.IOException;
public class MyTest {
private ZooKeeper zk;
// 实现一个 Watcher
private Watcher wh = new Watcher() {
// 重写 process 方法
public void process(WatchedEvent event) {
System.out.println(event);
}
};
// 连接 ZooKeeper 服务器
public void createZKInstance() throws IOException {
zk = new ZooKeeper("localhost:2181", 15000, this.wh);
}
// 同步创建节点
public String createNode() throws IOException, KeeperException, InterruptedException {
String ephemeralPath = zk.create("/zk-test-create-ephemeral", "ephemeral".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
return ephemeralPath;
}
// 同步删除节点
public void deleteNode() throws IOException {
zk.delete("/zk-test-create-ephemeral", -1);;
}
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
MyTest myTest = new MyTest();
// 连接 ZooKeeper 服务器
myTest.createZKInstance();
// 同步创建节点
String node = myTest.createNode();
// 输出节点
System.out.println(node);
// 同步删除节点
myTest.deleteNode();
}
}
执行结果:
WatchedEvent state:SyncConnected type:None path:null
/zk-test-create-ephemeral
WatchedEvent state:SyncConnected type:NodeDeleted path:/zk-test-create-ephemeral
上述代码中,我们使用 delete 方法删除了节点 /zk-test-create-ephemeral。返回的结果也显示“NodeDeleted”(节点被删除)。
编程要求
仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 间编写程序代码,实现以下需求:
- 在 createNodeSync 方法中使用异步创建节点的方法创建所有人可读的持久节点 /mynode1,节点数据为 This node is mine!,节点名称为 CreateMynode!,回调函数请使用“new test.MyStringCallback()” 对象;
- 在 deleteNode 方法中删除节点 /mynode1。
import org.apache.zookeeper.*;
import java.io.IOException;
public class Student {
// 初始化 ZooKeeper 实例
private ZooKeeper zk;
// 实现一个 Watcher
private Watcher wh = new Watcher() {
// 重写 process 方法
public void process(WatchedEvent event) {
System.out.println(event);
}
};
// 连接ZooKeeper服务器
public ZooKeeper createZKInstance() throws IOException {
zk = new ZooKeeper("localhost:2181", 15000, this.wh);
return zk;
}
// 使用同步方式删除节点 /mynode1
public void deleteNode() throws KeeperException, InterruptedException {
// 请在此处编写代码
/********* Begin *********/
zk.delete("/mynode1", -1);;
/********* End *********/
}
// 使用异步方式创建节点 /mynode1
public void createNodeSync() {
// 请在此处编写代码
/********* Begin *********/
zk.create("/mynode1","This node is mine!".getBytes(), ZooDefs.Ids.READ_ACL_UNSAFE, CreateMode.PERSISTENT,new test.MyStringCallback(),"CreateMynode!");
/********* End *********/
}
}