ZooKeeper作为一个分布式服务框架,本身使用Java编写,也对多种编程提供了API,这里记录一下通过java api来操作zookeeper.
创建ZooKeeper会话实例(连通zookeeper):
ZooKeeper客户端与服务器的连接过程是一个异步过程,也就是说在程序中,客户端代码在构造方法处理完初始化工作后会立即返回,大对数情况下此时并没有真正完成一个可用的会话连接,此时在会话的生命周期里处于"CONNECTION"状态。当该会话真正创建完毕后,ZooKeeper服务器会向会话对应的客户端发送一个事件通知以告知客户端,客户端只有在获取到这个通知后才算是真正的建立了一个会话连接.
package yzr.zk;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
/*
* 一个最基本的ZooKeeper会话实例
*/
public class zookeeper_constructor_usage_simple implements Watcher {
public static CountDownLatch connectionedSemaphore=new CountDownLatch(1);
/*
* (non-Javadoc)
* @see org.apache.zookeeper.Watcher#process(org.apache.zookeeper.WatchedEvent)
* 处理来自ZooKeeper服务器的Watch通知事件
* 在收到服务器发来的 SyncConnected事件之后,解除主程序中在计数器CountDownLatch上的等待阻塞.
*/
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: "+event);
if(KeeperState.SyncConnected==event.getState()){
connectionedSemaphore.countDown();
}
}
}
package yzr.run;
import org.apache.zookeeper.ZooKeeper;
import yzr.zk.zookeeper_constructor_usage_simple;
public class app {
public static void main(String[] args) throws Exception {
zookeeper_constructor_usage_simple zksimple=new zookeeper_constructor_usage_simple();
/*
* 异步初始化Zookeeper
*/
ZooKeeper zookeeper =new ZooKeeper("192.168.199.100:2181",5000,zksimple);
System.out.println(zookeeper.getState());
//等待阻塞
zksimple.connectionedSemaphore.await();
System.out.println("ZooKeeper会话连接建立完成!");
}
}
备注:CountDownLatch对象会在count递减到0时停止阻塞,在初始化构造中函数中指定count默认起始值,并且每调用一次countDown()方法,count值会减1直至为0,在await()的地方就会停止阻塞,使用程序继续执行。
复用SessionId和SessionPassword的ZooKeeper会话实例
在创建了与zookeeper正常的会话之后,zookeeper底层中会包含有该会话的一个id和password,可以借助此两个参数复用已经创建的会话连接。在zookeeper的构造函数中传入这两个参数即可。
package yzr.zk;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
/*
* 复用SessionID和SessionPassWd的ZooKeeper会话实例
*/
public class zookeeper_constuctor_usage_with_sid_password implements Watcher {
public static CountDownLatch connectionedSemaphore=new CountDownLatch(1);
/*
* (non-Javadoc)
* @see org.apache.zookeeper.Watcher#process(org.apache.zookeeper.WatchedEvent)
* 处理来自ZooKeeper服务器的Watch通知事件
* 在收到服务器发来的 SyncConnected事件之后,解除主程序中在计数器CountDownLatch上的等待阻塞.
*/
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: "+event);
if(KeeperState.SyncConnected==event.getState()){
connectionedSemaphore.countDown();
}
}
}
package yzr.run;
import org.apache.zookeeper.ZooKeeper;
import yzr.zk.zookeeper_constuctor_usage_with_sid_password;
public class app2 {
public static void main(String[] args) throws Exception {
zookeeper_constuctor_usage_with_sid_password zksimple=new zookeeper_constuctor_usage_with_sid_password();
ZooKeeper zookeeper =new ZooKeeper("192.168.199.100:2181",5000,zksimple);
zksimple.connectionedSemaphore.await();
//会话ID
long sessioniId=zookeeper.getSessionId();
//会话密码
byte[] pwd=zookeeper.getSessionPasswd();
/*
* ZooKeeper的构造函数中允许传入SessionID和SessionPasswd,可用于复用会话,以维持之前会话的有效性.
*/
zookeeper =new ZooKeeper("",5000,zksimple,sessioniId,pwd);
Thread.sleep(Integer.MAX_VALUE);
}
}
创建zookeeper节点:zookeeper提供了同步和异步两种api来实现zookeeper节点的操作。
创建节点 无论是同步还是异步的方式,ZooKeeper都不支持递归创建,无法在父节点不存在的情况创建子节点,另外,如果有节点已经存在,创建同名的节点的时候会抛出NodeExistsException异常,ZooKeeper的节点内容只支持byte[]数组类型,ZooKeeper不负责序列化的工作,需要我们自行序列化数据.如果创建的节点不需要权限控制,只需要在acl参数中传入Ids.OPEN_ACL_UNSAFE即可
同步 api:
package yzr.run;
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import yzr.zk.zookeeper_constructor_usage_simple;
public class create {
public static void main(String[] args) throws Exception {
zookeeper_constructor_usage_simple zksimple = new zookeeper_constructor_usage_simple();
/*
* ZooKeeper客户端与服务器的连接过程是一个异步过程,也就是说在程序中,构造方法会在处理完客户端初始化工作后会立即返回,
* 大对数情况下此时并没有真正完成一个可用的会话连接,在会话的生命周期里处于"CONNECTION"状态
* 当该会话真正创建完毕后,ZooKeeper服务器会向会话对应的客户端发送一个事件通知以告知客户端,客户端只有在获取到这个通知后,
* 才算是真正的建立了一个会话连接.
*/
ZooKeeper zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zksimple);
System.out.println(zookeeper.getState());
// 等待阻塞
zksimple.connectionedSemaphore.await();
//同步
// 无权限控制的临时节点
String path1 = zookeeper.create(
"/zk-create-test",
"test".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
System.out.println("成功创建了一个无权限控制的临时节点:" + path1);
//无权限控制的临时顺序节点
String path2 = zookeeper.create(
"/zk-create-test",
"test".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("成功创建了一个无权限控制的临时顺序节点:" + path2);
}
}
控制台消息:
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
CONNECTING
接收到的监听事件为: WatchedEvent state:SyncConnected type:None path:null
成功创建了一个无权限控制的临时节点:/zk-create-test
成功创建了一个无权限控制的临时顺序节点:/zk-create-test0000000006
异步api:
package yzr.run;
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import yzr.zk.zookeeper_constructor_usage_simple;
public class AsynCreate {
public static void main(String[] args) throws Exception {
zookeeper_constructor_usage_simple zksimple = new zookeeper_constructor_usage_simple();
/*
* ZooKeeper客户端与服务器的连接过程是一个异步过程,也就是说在程序中,构造方法会在处理完客户端初始化工作后会立即返回,
* 大对数情况下此时并没有真正完成一个可用的会话连接,在会话的生命周期里处于"CONNECTION"状态
* 当该会话真正创建完毕后,ZooKeeper服务器会向会话对应的客户端发送一个事件通知以告知客户端,客户端只有在获取到这个通知后,
* 才算是真正的建立了一个会话连接.
*/
ZooKeeper zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zksimple);
System.out.println(zookeeper.getState());
// 等待阻塞
zksimple.connectionedSemaphore.await();
//异步方式
System.out.println("异步创建节点");
//无权限控制的临时节点
zookeeper.create(
"/zk-create-test",
"test".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL,
new IStringCallback(),
"context");
//无权限控制的临时节点
zookeeper.create(
"/zk-create-test",
"".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL,
new IStringCallback(),
"context");
//无权限控制的临时顺序节点
zookeeper.create(
"/zk-create-test",
"test".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL,
new IStringCallback(),
"context");
//因为是异步创建,这里让程序不要那么快结束,然后就可以查看到异步创建节点的过程与结果
Thread.sleep(5000);
}
}
package yzr.run;
import org.apache.zookeeper.AsyncCallback.StringCallback;
public class IStringCallback implements StringCallback {
@Override
public void processResult(int rc, String path, Object ctx, String name) {
/*
* rc:ResultCode,服务端的响应码,可以根据rc识别出API调用的结果,常见的响应码如下:
* 0:ok调用成
* -4:客户端与服务端连接已经断开
* -110:指定节点已经存在
* -112:会话已经过期
*
* path:创建节点时传入的path值
*
* ctx:创建节点时传入的ctx值
*
* name:实际中在zooKeeper服务器上创建的节点路径名
*/
System.out.println("新建的节点路径结果是: [响应码数:"+rc+",指定的Path:"+path+",指定的ctx:"+ctx+",实际创建的路径名为:"+name+"]");
}
}
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
CONNECTING
接收到的监听事件为: WatchedEvent state:SyncConnected type:None path:null
异步创建节点
新建的节点路径结果是: [响应码数:0,指定的Path:/zk-create-test,指定的ctx:context,实际创建的路径名为:/zk-create-test]
新建的节点路径结果是: [响应码数:-110,指定的Path:/zk-create-test,指定的ctx:context,实际创建的路径名为:null]
新建的节点路径结果是: [响应码数:0,指定的Path:/zk-create-test,指定的ctx:context,实际创建的路径名为:/zk-create-test0000000011]
备注:/zk-create-test0000000011顺序节点中会在后面加上一串数字,这一串是作为排序用的,由zookeeper自动生成。在同一路径下创建相同节点是会出现的异常的,会抛出一个节点已存在的异常,返回的响应码是-110,正常的响应码为0.另外,还有-4(ConnectionLoss)客户端和服务端连接已经断开。-112(Session Expired)会话过期。
AsyncCallback包含了StatCallback,DataCallback,ACLCallback,ChildrenCallback,Children2Callback,StringCallback和VoidCallback七种不同的回调接口
获取zookeeper子节点列表:
如果zookeeper客户端在获取到指定节点的子节点列表后,还需要订阅这个子节点列表的变化通知,可以通过注册一个Watcher来实现.当有子节点,被添加或者删除的时候,服务端就会向客户端发送一个NodeChildrenChanged类型的事件通知,在服务端发送给客户端的事件通知中,是不包含最新的节点列表的,客户端必须主动重新进去获取.
同步api:
package yzr.zk;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
public class zookeeper_constructor_usage_watchnodechage implements Watcher {
public static CountDownLatch connectionedSemaphore=new CountDownLatch(1);
/*
* (non-Javadoc)
* @see org.apache.zookeeper.Watcher#process(org.apache.zookeeper.WatchedEvent)
* 处理来自ZooKeeper服务器的Watch通知事件
* 在收到服务器发来的 SyncConnected事件之后,解除主程序中在计数器CountDownLatch上的等待阻塞.
*/
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: "+event);
if(KeeperState.SyncConnected==event.getState()){
if(EventType.None==event.getType() && null ==event.getPath()){
connectionedSemaphore.countDown();
}
else if (event.getType()==EventType.NodeChildrenChanged){
//子节点发生变化
try {
System.out.println("\n重新加载子节点为:"+zookeeper.getChildren(event.getPath(),true));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static ZooKeeper zookeeper=null;
public static void main(String[] args) throws Exception {
zookeeper_constructor_usage_watchnodechage zk = new zookeeper_constructor_usage_watchnodechage();
/*
* ZooKeeper客户端与服务器的连接过程是一个异步过程,也就是说在程序中,构造方法会在处理完客户端初始化工作后会立即返回,
* 大对数情况下此时并没有真正完成一个可用的会话连接,在会话的生命周期里处于"CONNECTION"状态
* 当该会话真正创建完毕后,ZooKeeper服务器会向会话对应的客户端发送一个事件通知以告知客户端,客户端只有在获取到这个通知后,
* 才算是真正的建立了一个会话连接.
*/
zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zk);
System.out.println(zookeeper.getState());
// 等待阻塞
zk.connectionedSemaphore.await();
String path="/zk-test";
zookeeper.create(
path+"/t1",
"t1".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
List<String> chlidren=zookeeper.getChildren(path, true);
System.out.println("当前指定路径下的所有子节点为:"+chlidren);
zookeeper.create(
path+"/t2",
"t2".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
zookeeper.create(
path+"/t3",
"t3".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
Thread.sleep(5000);
}
}
控制台打印的消息:
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
CONNECTING
接收到的监听事件为: WatchedEvent state:SyncConnected type:None path:null
当前指定路径下的所有子节点为:[t1]
接收到的监听事件为: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zk-test
重新加载子节点为:[t1, t2]
接收到的监听事件为: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zk-test
重新加载子节点为:[t1, t2, t3]
[ ResultCode:0,Path:/zk-test,ctx:context,children:[t1, t2, t3],stat12884901897,12884901897,1501070933318,1501070933318,0,31,0,0,3,3,17179869189
]
异步api:
package yzr.zk;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import yzr.run.IChildren2Callback;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
public class zookeeper_constructor_usage_watchnodechage implements Watcher {
public static CountDownLatch connectionedSemaphore=new CountDownLatch(1);
/*
* (non-Javadoc)
* @see org.apache.zookeeper.Watcher#process(org.apache.zookeeper.WatchedEvent)
* 处理来自ZooKeeper服务器的Watch通知事件
* 在收到服务器发来的 SyncConnected事件之后,解除主程序中在计数器CountDownLatch上的等待阻塞.
*/
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: "+event);
if(KeeperState.SyncConnected==event.getState()){
if(EventType.None==event.getType() && null ==event.getPath()){
connectionedSemaphore.countDown();
}
else if (event.getType()==EventType.NodeChildrenChanged){
//子节点发生变化
try {
System.out.println("\n重新加载子节点为:"+zookeeper.getChildren(event.getPath(),true));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static ZooKeeper zookeeper=null;
public static void main(String[] args) throws Exception {
zookeeper_constructor_usage_watchnodechage zk = new zookeeper_constructor_usage_watchnodechage();
zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zk);
System.out.println(zookeeper.getState());
// 等待阻塞
zk.connectionedSemaphore.await();
String path="/zk-test";
zookeeper.create(
path+"/t1",
"t1".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
List<String> chlidren=zookeeper.getChildren(path, true);
System.out.println("当前指定路径下的所有子节点为:"+chlidren);
zookeeper.create(
path+"/t2",
"t2".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
zookeeper.create(
path+"/t3",
"t3".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
zookeeper.getChildren(path,true,new IChildren2Callback(),"context");
Thread.sleep(5000);
}
}
package yzr.run;
import java.util.List;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.data.Stat;
public class IChildren2Callback implements AsyncCallback.Children2Callback {
@Override
public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
System.out.println("[ ResultCode:"+rc+",Path:"+path+",ctx:"+ctx+",children:"+children+",stat"+stat+"]");
}
}
控制台打印的消息:
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
CONNECTING
接收到的监听事件为: WatchedEvent state:SyncConnected type:None path:null
当前指定路径下的所有子节点为:[t1]
接收到的监听事件为: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zk-test
重新加载子节点为:[t1, t2]
接收到的监听事件为: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zk-test
重新加载子节点为:[t1, t2, t3]
[ ResultCode:0,Path:/zk-test,ctx:context,children:[t1, t2, t3],stat12884901897,12884901897,1501070933318,1501070933318,0,31,0,0,3,3,17179869189
]
更新zookeeper节点数据内容:
同理还是有同步和异步两种方式,不过需要指出一点的是version参数的用法,此参数是用于指定节点的数据版本,如果此参数的值大于-1,表明本次更新操作是针对指定的数据版本进行的。讲到这里可以先来看一下CAS理论:通俗的讲就是对于值V,每次更新之前都会比较其预想值,只有符合预期,才会将V进行更新。zookepper的setData的version参数正是由CAS原理衍生出来的。具体来说,假设一个客户端进行更新操作的时候,如果携带了version参数,这执行期间,如果zookeeper上该节点刚刚好已经被更新过,那么其数据版本肯定是发生变化而导致version更新,所以是无法与传递的version参数值匹配的,于是便无法更新成功。这就有效避免了分布式更新的并发问题。
同步api:
package yzr.zk;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
public class zookeeper_setdata_api implements Watcher {
public static CountDownLatch connectionedSemaphore = new CountDownLatch(1);
private static Stat stat = new Stat();
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: " + event);
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectionedSemaphore.countDown();
} else if (event.getType() == EventType.NodeDataChanged) {
// 节点发生变化
try {
System.out.println("\n重新加载节点数据内容:" + new String(zookeeper.getData(event.getPath(), true, stat)));
// 打印节点状态信息
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static ZooKeeper zookeeper = null;
public static void main(String[] args) throws Exception {
System.out.println("-----------");
zookeeper_setdata_api zk = new zookeeper_setdata_api();
zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zk);
System.out.println(zookeeper.getState());
// 等待阻塞
zk.connectionedSemaphore.await();
String path = "/zk-test";
zookeeper.create(path + "/t1", "content".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
byte[] content = zookeeper.getData(path+"/t1", true, stat);
System.out.println("节点原始数据内容:" + new String(content));
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
// 修改节点数据内容
zookeeper.setData(path + "/t1", "new content".getBytes(), -1);
Thread.sleep(Integer.MAX_VALUE);
}
}
异步api:
package yzr.zk;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
import yzr.run.IStatCallback;
public class zookeeper_setdata_api_async implements Watcher {
public static CountDownLatch connectionedSemaphore = new CountDownLatch(1);
private static Stat stat = new Stat();
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: " + event);
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectionedSemaphore.countDown();
} else if (event.getType() == EventType.NodeDataChanged) {
// 节点发生变化
try {
System.out.println("\n重新加载节点数据内容:" + new String(zookeeper.getData(event.getPath(), true, stat)));
// 打印节点状态信息
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static ZooKeeper zookeeper = null;
public static void main(String[] args) throws Exception {
System.out.println("-----------");
zookeeper_setdata_api_async zk = new zookeeper_setdata_api_async();
zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zk);
System.out.println(zookeeper.getState());
// 等待阻塞
zk.connectionedSemaphore.await();
String path = "/zk-test";
zookeeper.create(path + "/t1", "content".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
byte[] content = zookeeper.getData(path+"/t1", true, stat);
System.out.println("节点原始数据内容:" + new String(content));
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
// 修改节点数据内容
zookeeper.setData(path + "/t1", "new content".getBytes(), -1,new IStatCallback(),null);
Thread.sleep(Integer.MAX_VALUE);
}
}
package yzr.run;
import org.apache.zookeeper.AsyncCallback.StatCallback;
import org.apache.zookeeper.data.Stat;
public class IStatCallback implements StatCallback {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
@Override
public void processResult(int rc, String path, Object ctx, Stat stat) {
if(rc==0){
System.out.println("success");
}
}
}
获取zookeeper节点值:
getData接口也是有同步和异步两种方式,客户端在获取某一zookeeper节点数据内容的时候,是可以进行Watcher注册的,一旦该注册过的节点发生状态变化,就没zookeeper服务端会触发一个NodeDataChanged事件通知客户端。
另外API返回的结果类型是byte[],需要自行序列化。
同步api:
package yzr.zk;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
/*
* 获取节点数据内容
*/
public class zookeeper_getData_API implements Watcher {
public static CountDownLatch connectionedSemaphore = new CountDownLatch(1);
private static Stat stat = new Stat();
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: " + event);
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectionedSemaphore.countDown();
} else if (event.getType() == EventType.NodeDataChanged) {
// 节点发生变化
try {
System.out.println("\n重新加载节点数据内容:" + new String(zookeeper.getData(event.getPath(), true, stat)));
// 打印节点状态信息
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static ZooKeeper zookeeper = null;
public static void main(String[] args) throws Exception {
System.out.println("-----------");
zookeeper_getData_API zk = new zookeeper_getData_API();
zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zk);
System.out.println(zookeeper.getState());
// 等待阻塞
zk.connectionedSemaphore.await();
String path = "/zk-test";
zookeeper.create(path + "/t1", "content".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
byte[] content = zookeeper.getData(path+"/t1", true, stat);
System.out.println("节点原始数据内容:" + new String(content));
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
// 修改节点数据内容
zookeeper.setData(path + "/t1", "new content".getBytes(), -1);
Thread.sleep(Integer.MAX_VALUE);
}
}
异步api:
package yzr.zk;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import yzr.run.IDataCallBack;
/*
* 获取节点数据内容
*/
public class zookeeper_getdata_async implements Watcher {
public static CountDownLatch connectionedSemaphore = new CountDownLatch(1);
private static Stat stat = new Stat();
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: " + event);
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectionedSemaphore.countDown();
} else if (event.getType() == EventType.NodeDataChanged) {
// 节点发生变化
try {
System.out.println("\n重新加载节点数据内容:");
zookeeper.getData(event.getPath(), true, new IDataCallBack(),null);
// 打印节点状态信息
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static ZooKeeper zookeeper = null;
public static void main(String[] args) throws Exception {
System.out.println("-----------");
zookeeper_getData_API zk = new zookeeper_getData_API();
zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zk);
System.out.println(zookeeper.getState());
// 等待阻塞
zk.connectionedSemaphore.await();
String path = "/zk-test";
zookeeper.create(path + "/t1", "content".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zookeeper.getData(path+"/t1", true, new IDataCallBack(),null);
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
// 修改节点数据内容
zookeeper.setData(path + "/t1", "new content".getBytes(), -1);
Thread.sleep(Integer.MAX_VALUE);
}
}
package yzr.run;
import org.apache.zookeeper.AsyncCallback.DataCallback;
import org.apache.zookeeper.data.Stat;
public class IDataCallBack implements DataCallback {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
@Override
public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
System.out.println("[ ResultCode:"+rc+",Path:"+path+",ctx:"+ctx+",data:"+new String(data)+"]");
System.out.println(
"事务ID:" + stat.getCzxid() + "," + stat.getMzxid() + ",节点内容版本:" + stat.getVersion());
}
}
控制台打印消息:
-----------
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
CONNECTING
接收到的监听事件为: WatchedEvent state:SyncConnected type:None path:null
节点原始数据内容:content
事务ID:17179869211,17179869211,节点内容版本:0
接收到的监听事件为: WatchedEvent state:SyncConnected type:NodeDataChanged path:/zk-test/t1
重新加载节点数据内容:new content
事务ID:17179869211,17179869212,节点内容版本:1
检测节点是否存在:
返回值是一个stat对象,如果在调用时注册了watcher,那么对节点是否进行监听,一旦节点被创建,被修改和删除都会通知客户端。
package yzr.zk;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import yzr.run.IChildren2Callback;
public class zookeeper_existes_api implements Watcher {
public static CountDownLatch connectionedSemaphore=new CountDownLatch(1);
/*
* (non-Javadoc)
* @see org.apache.zookeeper.Watcher#process(org.apache.zookeeper.WatchedEvent)
* 处理来自ZooKeeper服务器的Watch通知事件
* 在收到服务器发来的 SyncConnected事件之后,解除主程序中在计数器CountDownLatch上的等待阻塞.
*/
@Override
public void process(WatchedEvent event) {
System.out.println("接收到的监听事件为: "+event);
if(KeeperState.SyncConnected==event.getState()){
if(EventType.None==event.getType() && null ==event.getPath()){
connectionedSemaphore.countDown();
}
else if (event.getType()==EventType.NodeDataChanged){
//子节点发生变化
try {
System.out.println("Node Data Changed:"+event.getPath());
//重新注册
zookeeper.exists(event.getPath(), true);
} catch (Exception e) {
e.printStackTrace();
}
}
else if (event.getType()==EventType.NodeCreated){
//子节点发生变化
try {
System.out.println("Node Created:"+event.getPath());
//重新注册
zookeeper.exists(event.getPath(), true);
} catch (Exception e) {
e.printStackTrace();
}
}
else if (event.getType()==EventType.NodeDeleted){
//子节点发生变化
try {
System.out.println("Node Deleted:"+event.getPath());
//重新注册
zookeeper.exists(event.getPath(), true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static ZooKeeper zookeeper=null;
public static void main(String[] args) throws Exception {
zookeeper_existes_api zk = new zookeeper_existes_api();
/*
* ZooKeeper客户端与服务器的连接过程是一个异步过程,也就是说在程序中,构造方法会在处理完客户端初始化工作后会立即返回,
* 大对数情况下此时并没有真正完成一个可用的会话连接,在会话的生命周期里处于"CONNECTION"状态
* 当该会话真正创建完毕后,ZooKeeper服务器会向会话对应的客户端发送一个事件通知以告知客户端,客户端只有在获取到这个通知后,
* 才算是真正的建立了一个会话连接.
*/
zookeeper = new ZooKeeper("192.168.199.100:2181", 5000, zk);
System.out.println(zookeeper.getState());
// 等待阻塞
zk.connectionedSemaphore.await();
String path="/zk-test/t2";
zookeeper.exists(path, true);
zookeeper.create(
path,
"tttt".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
zookeeper.setData(path, "yyyy".getBytes(), -1);
zookeeper.delete(path, -1);
Thread.sleep(5000);
}
}
打印消息:
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
CONNECTING
接收到的监听事件为: WatchedEvent state:SyncConnected type:None path:null
接收到的监听事件为: WatchedEvent state:SyncConnected type:NodeCreated path:/zk-test/t2
Node Created:/zk-test/t2
接收到的监听事件为: WatchedEvent state:SyncConnected type:NodeDataChanged path:/zk-test/t2
Node Data Changed:/zk-test/t2
接收到的监听事件为: WatchedEvent state:SyncConnected type:NodeDeleted path:/zk-test/t2
Node Deleted:/zk-test/t2