zookeeper(三)java操作zookeeper

首先要使用java操作zookeeper,zookeeper的javaclient是我们更轻松地去对zookeeper进行各种操作,我们引入zookeeper-3.3.4.jar和zkclient-0.1.jar即可。

zookeeper-3.3.4.jar为官方提供的javaAPI,zkclient-0.1.jar则为在原生api基础上进行扩展的开源JAVA客户端。

(1)创建会话方法

客户端可以通过一个zookeeper实例来连接zookeeper服务器。

Zookeeper(Arguments)方法(一共有4个构造方法,根据参数不同)

参数说明如下:

connectString:连接服务器列表,用"逗号"分割。

sessionTimeout:心跳检测时间周期(毫秒)。

wather:事件处理通知器。

canBeReadOnly:标识当前会话是否支持只读。

sessionIdsessionPassword:提供连接zookeeper的sessionId和密码,通过这两个确定唯一一台客户端,目的是客户提供重复会话。

注意:zookeeper客户端和服务器端会话的建立是一个异步过程,也就是说在程序中,我们程序方法在处理完成客户端初始化后立即返回(也就是说程序往下执行代码,这样,大多数情况下我们并没有真正构建好一个可用会话,在会话的生命周期处于"CONNECTING"时才算真正建立完毕,所以我们需要使用多线程中所学习的一个小工具类)

(2)创建节点(znode)方法:create

提供了两种创建节点的方法:同步和异步创建节点方式

同步方式:

参数1:节点路径(名称)/nodename

(不允许递归创建节点,也就是说在父节点不存在的情况下,不允许创建子节点)

参数2:节点内容:要求类型是字节数组

(也就是说,不支持序列化方式,如果需要实现序列化,可使用java相关序列化框架,如Hessioan,Kryo框架)

参数3:节点权限:使用Ids.OPEN_ACL_UNSAFE开发权限即可。

(这个参数一般在权限没有太高要求的场景下,没必要关注)

参数4:节点类型:创建节点的类型,CreateMode.*,提供四种节点类型

PERSISTENT:持久节点

PERSISTENT_SEQUENTIAL:持久顺序节点

EPHEMERAL:临时节点

EPHEMERAL_SEQUENTIAL:临时顺序节点

异步方式:(在同步参数基础上增加两个参数)

参数5:注册一个异步回调函数,要实现AsynCallBack .StringCallBack借口,重写processResult(int rc,String path,Object ctx,String name)方法,当节点创建完毕后执行此方法。

rc:为服务端响应码 0 表示调用成功,-4 表示端口连接、-110 表示指定节点存在,-112表示会话已经过期

path:接口调用时传入API的数据节点的路径参数

ctx:为调用接口传入API的ctx的值

name:实际在服务端创建节点的名称

参数6:传递给回调函数的参数,一般为上下文(Context)信息。

 

(3)删除节点:delete方法

(api提供了两个接口:同步删除和异步删除方式)

同步方式:

  参数1:节点名称 /deletePath

  参数2:版本号,即表明本次删除操作是针对该数据的某个版本进行的操作。

异步方式:(和create方法一致)

  参数3:一个异步回调函数

  参数4:用于传递上下文信息的对象。

注意:在zookeeper中,只允许删除子节点信息,也就是说如果当前节点不是子节点则无法删除,或必须先删除其下所有子节点。

 

 

(4)getChildren读取数据方法:包括子节点列表的获取和子节点数据的获取

参数1,path:获取指定节点下的数据(获取子节点列表)

参数2,watcher:注册的watcher,一旦在本次子节点获取后,子节点列表发生变更的话,那么就会向客户端发送通知。该参数允许为null。

参数3,wath:表明是否需要注册一个watcher;如果为true,则会使用到zookeeper客户端上文中提到的那个默认watcher。如果为false,则表明不需要注册watcher。

参数4,cb:回调函数

参数5,ctx:上下文信息对象。

参数6,stat:指定数据节点的节点状态信息

注意:当我们获取指定节点的子节点列表后,还需要订阅这个子节点列表的变化通知,这时候就可以通过注册一个watcher来实现,当子节点被添加火删除时,服务器端就会触发一个“NodeChildrenChanged”类型的事件通知,需要注意的是服务器端发送给客户端的事件通知中,是不包含最新的节点列表的,客户端必须主动从新进行获取,通常在客户端收到这个事件通知后,就可以再次主动获取最新的子节点列表了。也就是说,zookeeper服务端在向客户端发送watcher“NodeChildrenChanged”事件通知的时候,仅仅只发了一个通知,不会把节点变化情况发给客户端,需要客户端自己重新获取,另外Watcher通知是一次性的,即触发后失效,因此客户需要反复注册watcher才行。

 

(5)getData方法:获取指定节点的数据内容

 参数1,path:路径

 参数2,watcher:注册的watcher对象。一旦之后节点内容有变更,则会像客户端发送通知,该参数允许为null。

参数3,stat:指定节点的状态信息

参数4,watch:是否使用watcher,如果为true则使用默认上文中的watcher,false则不使用watcher。

参数5,cb:回调函数

参数6,ctx:用于传递的上下文信息对象。

注意:该方法和getChildren方法基本相同,主要是注册的watcher有所不同,客户端在获取一个阶段数据内容时,是可以进行watcher注册的,一旦节点发生变更,则服务器端会发送给客户端一个NodeDataChanged的事件通知

 

(6)setData方法:修改指定节点的数据内容

 参数1,path:路径。

参数2,data:数据内容。

参数3,版本号(-1覆盖之前所有的版本)

参数4,cb:回调函数

参数5:ctx:用于传递的上下文对象。

(7)exists方法:检测节点是否存在

 参数1,path:路径

参数2,watcher:注册的watcher对象。一旦节点内容有变更,则会像客户端发送通知,该参数允许为null。(用于三类事件监听:节点的创建,删除,更新)

参数3,watch:是否使用watcher,如果为true则使用默认上文中的watcher,false则不使用watcher。

参数4,cb:回调函数。

参数5,ctx:用于传递的下文信息对象。

注意:exists方法意义在于无论节点是否存在,都可以进行注册watcher,能够对节点的创建,删除,和修改进行监听,但是其子节点发生的各种变化,都不会通知客户端。

 

 

 

java操作zookeeper的示例代码:

 1 import java.util.concurrent.CountDownLatch;
 2 import org.apache.zookeeper.CreateMode;
 3 import org.apache.zookeeper.WatchedEvent;
 4 import org.apache.zookeeper.Watcher;
 5 import org.apache.zookeeper.Watcher.Event.EventType;
 6 import org.apache.zookeeper.ZooKeeper;
 7 import org.apache.zookeeper.Watcher.Event.KeeperState;
 8 import org.apache.zookeeper.ZooDefs.Ids;
 9 
10 /**
11  * Zookeeper base学习笔记
12  */
13 public class ZookeeperBase {
14 
15     /** zookeeper地址 */
16     static final String CONNECT_ADDR = "127.0.0.1:2181";
17     /** session超时时间 */
18     static final int SESSION_OUTTIME = 2000;//ms 
19     /** 信号量,阻塞程序执行,用于等待zookeeper连接成功,发送成功信号 */
20     static final CountDownLatch connectedSemaphore = new CountDownLatch(1);
21     
22     public static void main(String[] args) throws Exception{
23         
24         ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher(){
25             @Override
26             public void process(WatchedEvent event) {
27                 //获取事件的状态
28                 KeeperState keeperState = event.getState();
29                 EventType eventType = event.getType();
30                 //如果是建立连接
31                 if(KeeperState.SyncConnected == keeperState){
32                     if(EventType.None == eventType){
33                         //如果建立连接成功,则发送信号量,让后续阻塞程序向下执行
34                         connectedSemaphore.countDown();
35                         System.out.println("zk 建立连接");
36                     }
37                 }
38             }
39         });
40 
41         //进行阻塞
42         connectedSemaphore.await();
43         
44         System.out.println("..");
45         //创建父节点
46         zk.create("/testRoot", "testRoot".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
47         
48         //创建子节点
49         zk.create("/testRoot/children", "children data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
50         zk.create("/testRoot/children2", "children2 data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
51         
52         //获取节点洗信息
53         byte[] data = zk.getData("/testRoot", false, null);
54         System.out.println(new String(data));
55         System.out.println(zk.getChildren("/testRoot", false));
56         
57         //修改节点的值
58         zk.setData("/testRoot", "modify data root".getBytes(), -1);
59         byte[] data2 = zk.getData("/testRoot", false, null);
60         System.out.println(new String(data2));        
61         
62         //判断节点是否存在
63         System.out.println(zk.exists("/testRoot/children", false));
64         
65         //删除节点
66         zk.delete("/testRoot/children2", -1);
67         System.out.println(zk.exists("/testRoot/children2", false));
68         
69         zk.close();
70         
71         
72         
73     }
74     
75 }

 

posted @ 2017-10-31 22:38  喻聪  阅读(1682)  评论(0编辑  收藏  举报