Zookeeper Java API
概述
- Zookeeper提供了Java API方便我们来操作zk服务,可以通过maven引入zk的相关依赖包。
- 通过org.apache.zookeeper.Zookeeper类创建连接zk服务器的示例对象,在创建过程中给定zk服务器地址、会话持续时间以及监视器三个参数,当连接创建成功后,通过Zookeeper实例提供的接口(或方法)来和服务器进行交互。
- Pom.xml文件依赖内容如下:
org.apache.zookeeper zookeeper 3.4.5
连接创建
使用Zookeeper类来表示连接,创建的该实例对象有四个构造方法来调用:
Zookeeper(connectString,sessionTimeout,watcher); ★//最常用 Zookeeper(connectString,sessionTimeout,watcher,canBeReadOnly);★//最常用 Zookeeper(connectString,sessionTimeout, watcher,sessionId,sessionPasswd) ; Zookeeper(connectString,sessionTimeout,watcher,sessionId,sessionPasswd,canBeReadOnly);
其中第一个构造方法底层调用第二个构造方法,只是canBeReadOnly参数设置为false。
参数说明:
1、connectString:参数为zk集群服务器的连接url,当给定路径的时候,表示所有的操作都是基于该路径进行操作的(路径只可以添加到最后)。
例如:”www.mareenoire.info:2181, www.mareenoire.info:2182, www.mareenoire.info:2183/app”。
2、sessionTimeout:为会话过期时间,以毫秒为单位,一般设置为tickTime的3-4倍;
客户端和服务器端之间的连接通过心跳包进行维系,如果心跳包超过这个指定时间则认为会话超时失效。一般设置为private static final int SESSION_TIMEOUT = 30000;
3、watcher:是监视器,用于触发相应事件,可以为空(表示不需要观察者);
4、canBeReadOnly:是否支持只读连接,默认为false。
5、sessionId、SessionPassword :会话编号 会话密码,用来实现会话恢复。
**注意1:整个创建会话的过程是异步的,构造方法会在初始化连接后即返回,并不代表真正建立好了一个会话,此时会话处于”CONNECTING”状态。
**注意2:当会话真正创建起来后,服务器会发送事件通知给客户端,只有客户端获取到这个通知后,会话才真正建立。
新增/创建节点
- ZK中新增子节点和创建节点其实是同一个含义,创建一个节点其实就相当于在根目录下新增一个子节点,
- 注意:zk不支持为不存在的父节点创建子节点(不支持循环创建)。
- 创建节点的时候要求指明节点被创建的类型(CreateMode)。
- 调用Zookeeper实例的create方法,需要给定的参数有:
//同步方式创建
String create(final String path,byte data[],List acl,CreateMode createMode);
说明:返回的是该节点的路径名称,例如:/test/zh_1324578
//异步方式创建【不常用】
void create(final String path,byte data[],List acl,CreateMode createMode,StringCallback cb,Object ctx);
说明:此创建方式是通过回调函数来相应操作。
参数说明:
1. path——要创建的数据节点的路径
2. data []——节点创建时初始数据内容
3. acl——节点acl安全策略,不考虑权限的情况下给定:www.mareenoire.info_ACL_UNSAFE。
4. createMode——创建模式
CreateMode类型 名称 详解 PERSISTENT 持久 会话结束后不会被自动删除 PERSISTENT_SEQUENTIAL 持久顺序 在节点名称后添加一个序列号(单调递增),不会自动删除 EPHEMERAL 临时 在会话结束后自动被删除 EPHEMERAL_SEQUENTIAL 临时顺序 在会话被结束后自动删除,会在给定的path节点名称后添加一个序列号(单调递增) 5. cb——回调接口
6. ctx——传递对象,用来在回调方法中使用 通常是个上下文对象
**注意:不支持递归创建,即不能在无父节点的情况下创建出子节点,尝试创建已经存在的节点将失败并抛出异常,在不需要进行任何权限控制时,只需传入www.mareenoire.info_ACL_UNSAFE即可。
删除节点
当系统不需要某个配置节点的时候,或者某个节点失效的时候,使用delete方法可以删除该节点;
**注意:无法删除存在子节点的节点,即如果要删除一个节点,必须要先删除其所有子节点【不支持递归删除】
删除要求:被删除的节点木有子节点,并且需要给定明确的版本号(可以给定-1,表示不管版本号是什么都删除)
例如:
client.delete("/root/child", -1);//不管版本号直接删除
client.delete("/root", 0);//直接删除版本号为0的root节点,如果zk上root节点的版本是0,那么删除成功,否则抛出异常。
public void delete(final String path,int version)
说明:无返回类型
public void delete(final String path,int version,VoidCallback cb,Object ctx)
说明:无返回类型
获取子节点名称列表信息
//同步方式
List getChildren(final String path,Watcher watcher)List getChildren(String path,boolean watch)List getChildren(final String path,Watcher watcher,Stat stat)List getChildren(String path,boolean watch,Stat stat)
说明:上述返回的都是path路径下的节点名称
//异步方式
void getChildred(final String path,Watcher watcher,ChildrenCallback cb,Object ctx)void getChildred(String path,boolean watch,ChildrednCallback cb,Object ctx)void getChildred(final String path,Watcher watcher,Children2Callback cb,Object ctx)void getChildred(String path,boolean watch,Children2Callback cb,Object ctx)
参数说明
- path 要创建的数据节点的路径
- watcher 观察者,一旦在本子节点获取之后,子节点列表发生变更,服务器端向客户端发送消息,触发watcher中的回调。注意,仅仅是通知而已,如果需要新的子节点列表,需要自己再次去获取。允许传入null。
- watch 表明是否需要注册一个Watcher。为true则通知默认到默认watcher,如果为false则不使用
- cb 回掉函数
- ctx 上下文对象
- stat 指定数据节点的状态信息。用法是在接口中传入一个旧的stat变量,该stat变量会在方法执行过程中,被来自服务端响应的新stat对象替换。
获取节点数据
**注意:可以通过注册Watcher进行监听,一旦该节点数据被更新会通知客户端
例如:String data=new String(client.getData("/root/child", false, null));//获取数据,不进行wath机制监控,state状态信息为空
//同步方式
byte [] getData(final String path,Watcher watcher, Stat stat)byte [] getData(String path,boolean watch, Stat stat)
//异步方式
void getData(final String path,Watcher watcher, DataCallback cb,Object ctx) void getData(String path,boolean watch, DataCallback cb,Object ctx)
更新数据
当节点内容需要进行改变的时候可以调用setDate方法设置节点内容;
注意:设置节点内容时需要给定版本号,zk服务器会检查该版本号;
如果当前节点和你给定的版本号不一致,那么直接抛出异常,否则更新成功。
如果给定的版本号为-1,那么表示不检查。
例如:client.setData("/root/child", "new-data".getBytes(), -1);//设置新的内容
//同步方式
Stat setData(final String path,byte data[],int version) //version
说明:可以传入-1,表明要基于最新版本进行更新操作
//异步方式
void setData(final String path,byte data[],int version,StatCallback cb,Object ctx)
检查节点是否存在
**注意:可以通过注册Watcher进行监听,一旦节点被创建、删除、数据被更新都会通知客户端
//同步方式
public Stat exists(final String path,Watcher watcher)public Stat exists(String path,boolean watch)
//异步方式
public Stat exists(final String path,Watcher watcher,StatCallback cb,Object ctx) public Stat exists(String path,boolean watch,StatCallback cb,Object ctx)
其他方法
- addAuthInfo:添加权限验证scheme 信息
- getACL:获取节点的权限列表
- setACL:设置节点的权限列表
- getState:获取当前连接的States 信息
代码案例
创建节点
package com.master.zookeeper;import java.io.IOException;import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper;public class DemoCreate {public static String Url_1 = "192.168.1.111,192.168.1.111:2182,192.168.1.111:2183";// 端口号不一定,随意选择public static String Url_2 = "192.168.1.111,192.168.1.111:2182,192.168.1.111:2183/app";// 端口号不一定,随意选择,给定路径public static void main(String[] args) { // test1(); // test2();}/*** 测试创建连接的时候给定路径* @throws IOException* @throws KeeperException* @throws InterruptedException*/static void test2() throws IOException, KeeperException, InterruptedException {ZooKeeper client = new ZooKeeper(Url_2, 2000, new Watcher() {@Overridepublic void process(WatchedEvent arg0) {}});// 创建永久节点String result = client.create("/root", null, www.mareenoire.info_ACL_UNSAFE, CreateMode.PERSISTENT);System.out.println("创建永久节点/root结果:" + result);// 添加子节点——永久顺序节点result = client.create("/root/child", "child".getBytes(), www.mareenoire.info_ACL_UNSAFE,CreateMode.PERSISTENT_SEQUENTIAL);System.out.println("添加节点/root/child结果:" + result);// 创建临时节点result = client.create("/tmp", "".getBytes(), www.mareenoire.info_ACL_UNSAFE, CreateMode.EPHEMERAL);System.out.println("创建临时节点/root结果:" + result);// 创建临时顺序节点result = client.create("/tmp", "".getBytes(), www.mareenoire.info_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);System.out.println("创建临时顺序节点/root结果:" + result);Thread.sleep(10000);// 关闭会话client.close();}static void test1() throws IOException, KeeperException, InterruptedException {ZooKeeper client = new ZooKeeper(Url_1, 2000, new Watcher() {@Overridepublic void process(WatchedEvent arg0) {}});// 创建永久节点String result = client.create("/root", null, www.mareenoire.info_ACL_UNSAFE, CreateMode.PERSISTENT);System.out.println("创建永久节点/root结果:" + result);// 添加子节点——永久顺序节点result = client.create("/root/child", "child".getBytes(), www.mareenoire.info_ACL_UNSAFE,CreateMode.PERSISTENT_SEQUENTIAL);System.out.println("添加节点/root/child结果:" + result);// 创建临时节点result = client.create("/tmp", "".getBytes(), www.mareenoire.info_ACL_UNSAFE, CreateMode.EPHEMERAL);System.out.println("创建临时节点/root结果:" + result);// 创建临时顺序节点result = client.create("/tmp", "".getBytes(), www.mareenoire.info_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);System.out.println("创建临时顺序节点/root结果:" + result);Thread.sleep(5000);// 关闭会话client.close();}}
删除节点
package com.master.zookeeper;import java.io.IOException;import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper;public class DemoDelete {public static String Url_1 = "192.168.1.111,192.168.1.111:2182,192.168.1.111:2183";// 端口号不一定,随意选择public static String Url_2 = "192.168.1.111,192.168.1.111:2182,192.168.1.111:2183/app";// 端口号不一定,随意选择,给定路径public static void main(String[] args) {}static void test1() throws IOException, InterruptedException, KeeperException{ZooKeeper client = new ZooKeeper(Url_1, 2000, new Watcher() {@Overridepublic void process(WatchedEvent arg0) {}});//删除节点 /root/childclient.delete("/root/child", -1);//给定具体的版本号进行删除rootclient.delete("/root", client.exists("/root", false).getVersion());//删除文件夹——递归删除client.delete("/app", -1);//不支持递归删除client.close();}}
设置获取节点数据
package com.master.zookeeper;import java.io.IOException;import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper;/*** 演示设置数据和读取数据* * @author Administrator**/ public class DemoData {public static String Url_1 = "192.168.1.111,192.168.1.111:2182,192.168.1.111:2183";// 端口号不一定,随意选择public static String Url_2 = "192.168.1.111,192.168.1.111:2182,192.168.1.111:2183/app";// 端口号不一定,随意选择,给定路径public static void main(String[] args) {}static void test1() throws IOException, InterruptedException, KeeperException {ZooKeeper client = new ZooKeeper(Url_1, 2000, new Watcher() {@Overridepublic void process(WatchedEvent arg0) {}});String data = "";// 获取数据// 第一种方式:当第二个参数为true的时候,会使用创建client时候给定的watcher实例进行监控data = new String(client.getData("/root/child", false, null));// 第二种方式:采用给定的监视器进行监控 // data = new String(client.getData("/root/child", new Watcher() { // @Override // public void process(WatchedEvent arg0) { // } // }, null));// 设置数据client.setData("/root/child", "new-data".getBytes(), -1);// 再重新获取数据data = new String(client.getData("/root/child", new Watcher() {@Overridepublic void process(WatchedEvent arg0) {}}, null));client.close();}}