对于Zookeeper的建立连接、增删改查、以及监视节点的变化操作。
一、简单实例操作zookeeper原生API
1. 创建会话方法:客户端可以通过创建一个zookeeper实例来连接zookeeper服务器。
参数说明:
connectString:连接服务器列表,用“,”分割;
sessionTimeout:心跳检测时间周期(毫秒);
watcher:事件处理通知器;
canBeReadOnly:标识当前会话是否支持只读;
sessionId, sessionPasswd:提供链接zookeeper的sessionId和密码,通过这俩确定唯一一台客户端,目的是可以提供重复会话;
注意:zookeeper客户端和服务器端会话的建立是一个异步的过程。
static final String CONNECT_ADDR = "192.168.80.88:2181,192.168.80.87:2181,192.168.80.86:2181";
static final int SESSION_OUTTIME = 2000;//ms
static final CountDownLatch connectedSemaphore = new CountDownLatch(1);
//创建zookeeper连接
ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher(){
@Override
public void process(WatchedEvent event) {
//连接状态
KeeperState keeperState = event.getState();
//事件类型
EventType eventType = event.getType();
//如果是建立连接
if(KeeperState.SyncConnected == keeperState){
if(EventType.None == eventType){
//如果建立连接成功,则发送信号量,让后续阻塞程序向下执行
connectedSemaphore.countDown();
System.out.println("zk 建立连接");
}
}
}
});
//进行阻塞
connectedSemaphore.await();
2. 创建节点(znode)方法:create 提供同步和异步两种方式
同步方式:
参数说明:
path:节点路径(名称),不允许递归创建节点;
data:节点内容,是字节数组,不支持序列化方式,如果需要序列化,可使用java相关的序列化框架如Hessian、Kryo框架;
acl: 节点权限,使用Ids.OPEN_ACL_UNSAFE开放权限即可;
createMode:节点类型,提供了以下四种
PERSISTENT(持久节点)
PERSISTENT_SEQUENTIAL(持久顺序节点)
EPHEMERAL(临时节点)
EPHEMERAL_SEQUENTIAL(临时顺序节点)
//创建父节点,不允许递归创建节点,不支持序列化方式
zk.
create
("/testRoot", "testRoot".getBytes(),
Ids.OPEN_ACL_UNSAFE
,
CreateMode.PERSISTENT
);
异步方式:(再同步的基础上添加两个参数)
参数说明:
StringCallback:注册一个异步回调函数,要实现AsynCallBack.StringCallBack接口,重写proce***esult()方法,当节点创建完毕后执行此方法;
·rc:服务器响应码 0表示成功-4表示连接 -110表示制定节点存在 -112表示会话已过期
·path:接口调用时传入API的数据节点的路径参数
·ctx:为调用接口传入API的ctx,
·name:实际在服务器端创建节点的名称
Object:传递给回调函数的参数,一般为上下文信息;
//异步创建节点
zooKeeper.create("/apis/","create api1".getBytes(),
Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL,
new StringCallback(){
public void proce***esult(int rc, String path,Object ctx, String name) {
if(rc==0){
System.out.println("创建节点完成");
countDownLatch.countDown();
}
}
},"12345");
3. 判断节点(znode)是否存在:exists
参数说明:
path:路径
watcher:注册的watcher对象,一旦之后节点内容有变更,则会向客户端发送通知,该参数可以为null。(用于三类事件监听:节点的创建、删除、更新)
watch:是否使用watcher,如果为true则默认使用上文中的watcher。false则不使用watcher。
cb:回调函数
ctx:用于传递的上下文信息对象
注意:exists方法的意义在于无论节点是否存在,都可以进行注册watcher,能够对节点的创建、删除、修改进行监听,但是其子节点变化,不会通知客户端。
//判断节点是否存在
zk.exists("/testRoot/children", false)
4. 获得节点(znode)数据:getData
参数说明:
path:路径
watcher:注册的watcher对象,一旦之后节点内容有变更,则会向客户端发送通知,该参数可以为null。(用于三类事件监听:节点的创建、删除、更新)
watch:是否使用watcher,如果为true则默认使用上文中的watcher。false则不使用watcher。
//获取节点信息
byte[] data = zk.getData("/testRoot", false, null);
System.out.println(new String(data));
5. 修改节点(znode)数据:setData
参数说明:
path:路径
data:节点内容,是字节数组,不支持序列化方式,如果需要序列化,可使用java相关的序列化框架如Hessian、Kryo框架;
version:版本号,-1则跳过版本检查;
//修改节点的值
zk.setData("/testRoot", "modify data root".getBytes(), -1);
6. 遍历子节点:getChildren
参数说明:
path:路径
watcher:注册的watcher对象,一旦在本次节点获取后,子节点列表发生变更的话,那么会向客户端发出通知。
watch:是否需要注册一个watcher,如果为true则默认zookeeper客户端上文中的watcher。false则不使用watcher。
stat:指定数据节点的节点状态信息。
注意:当子节点被添加或删除时,服务器就会触发一个NodeChildrenChanged类型的事件通知,该通知中不包含最新的节点列表。客户端必须主动重新获取。watcher是一次性的,即触发后失效,因此客户端需要反复注册。
//遍历节点下的所有数据
List<String> nodeChildName=zookeeper.getChildren("/testRoot", false);
for(String path:nodeChildName){
//获得节点的数据
byte[] data=zookeeper.getData(("/testRoot/"+path), false, null);
//修改节点的数据
zookeeper.setData("/testRoot/"+path, (path+"newData").getBytes() , -1);
}
7. 删除节点(znode)数据:delete
参数说明:
path:路径
version:版本号,-1则跳过版本检查;
//删除节点,只能删除叶子节点
zk.delete("/testRoot/children", -1);
//关闭连接
zk.close();
注意:在zookeeper中,不允许级联删除。必须先删除子节点,再删除其父节点。
二、Watcher
zookeeper有watch事件,是一次性触发的,当watch监视的数据发生变化时,通知设置了该watch的client,即watcher。watcher是监听数据发送了某些变化,有对应的事件类型和状态类型。
·事件类型EventType:(zonde节点相关的)
·状态类型KeeperState:(与客户端实例相关的)
watcher的特性:一次性、客户端串行执行、轻量。
一次性:zookeeper有watch事件,是一次性触发的,当watch监视的数据发生变化时,通知设置了该watch的client,即watcher,由于zookeeper的监控都是一次性的所以每次必须设置监控。
客户端串行执行:客户端watcher回调的过程是一个串行同步的过程。
轻量:WatchedEvent是zookeeper整个Watcher通知机制的最小通知单元,包括三部分:通知状态、事件类型和节点路径。也就是说Watcher通知只会告诉客户端发生了事件而不会告诉其具体内容,需要客户自己进行获取。
public class WatchedEvent {
final private KeeperState keeperState;
final private EventType eventType;
private String path;
}
设置监听的方法有以下方法
1)监听节点的创建、修改、删除,对应的事件为:NodeDataChanged\NodeCreated\NodeDeleted
zookeeper.exists(path, true);
zookeeper.getData(path, true, null);
2)监听子节点创建和删除,对应的事件:NodeChildrenChanged
zookeeper.getChildren(path, true);
至此Zookeeper的原生API的基本操作已将讲完,下一章节主要讲curator框架操作zookeeper