原生API
首先导入jar包:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.8</version>
</dependency>
1.建立session会话
public class CreateSessionDemo {
//zookeeper集群地址
private final static String CONNECTSTRING="192.168.74.131:2181,192.168.74.132:2181,192.168.74.133:2181";
//并发包中的计数器
private static CountDownLatch countDownLatch=new CountDownLatch(1);
public static void main(String[] args) throws IOException, InterruptedException {
//5000 session过期时间 超过5秒连接会断掉
//watcher 监控机制
ZooKeeper zooKeeper=new ZooKeeper(CONNECTSTRING, 5000, new Watcher() {
public void process(WatchedEvent watchedEvent) {
//如果当前的连接状态是连接成功的,那么通过计数器去控制 计数器-1
if(watchedEvent.getState()==Event.KeeperState.SyncConnected){
countDownLatch.countDown();
System.out.println(watchedEvent.getState());
}
}
});
countDownLatch.await(); //调用await的线程会被挂起 直到CountDownLatch中的值为0
System.out.println(zooKeeper.getState());
}
}
运行结果:
名词解析:
createMode类型解析:
persistent 持久化节点
persistent sequential 持久化有序节点
ephemeral 临时节点
ephemeral sequential 临时有序节点
这个其实就对应了命令行中的:create -s -e path data acl 中的-s和-e
ZooDefs.Ids解析:
看下么源码图与命令行图,可以看出其实就是对权限控制的封装。
源码图:
命令行图:
2.创建节点与监听
public class ApiOperatorDemo implements Watcher{
//连接地址及端口号
private final static String CONNECTSTRING="192.168.74.131:2181,192.168.74.132:2181,192.168.74.133:2181";
//并发包工具类
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static CountDownLatch countDownLatch2 = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
//节点状态信息
private static Stat stat = new Stat();
public static void main(String[] args) throws Exception{
zooKeeper = new ZooKeeper(CONNECTSTRING, 10000, new ApiOperatorDemo());
countDownLatch.await();
//使用exists给createTest节点创建监听,并返回stat,stat为空则表示当前节点不存在
Stat stat = zooKeeper.exists("/createTest",true);
//创建节点
zooKeeper.create("/createTest","test".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
//这里需要让main线程sleep一下或者await一下,如果不sleep会导致main执行完成,但是服务端向客户端发送的watch通知还没到达
// Thread.sleep(2000);
countDownLatch2.await();
//创建子节点 子节点与上面类似 只有一点需要注意,就是父节点必须是持久化节点不能是临时节点 。临时节点不能有子节点。
}
public void process(WatchedEvent watchedEvent) {
//如果当前的连接状态是连接成功的,那么通过计数器去控制
if(watchedEvent.getState() == Event.KeeperState.SyncConnected){
//第一次进来的连接状态
if(Event.EventType.None==watchedEvent.getType()&&null==watchedEvent.getPath()){
countDownLatch.countDown();
System.out.println(watchedEvent.getState()+"-->"+watchedEvent.getType());
}
//创建子节点的时候会触发
else if(watchedEvent.getType()== Event.EventType.NodeCreated){
try {
//通过路径获取数据将数据存储在stat中,true表示再注册一次通知,因为通知是一次失效的
byte[] data = zooKeeper.getData(watchedEvent.getPath(),true,stat);
System.out.println("stat:"+stat);
System.out.println("节点创建路径:"+watchedEvent.getPath()+"->节点的值:"+data);
countDownLatch2.countDown();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
修改节点与监听:
public class ApiOperatorDemo implements Watcher{
//连接地址及端口号
private final static String CONNECTSTRING="192.168.74.131:2181,192.168.74.132:2181,192.168.74.133:2181";
//并发包工具类
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static CountDownLatch countDownLatch2 = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
//节点状态信息
private static Stat stat = new Stat();
public static void main(String[] args) throws Exception{
zooKeeper = new ZooKeeper(CONNECTSTRING, 10000, new ApiOperatorDemo());
countDownLatch.await();
//使用exist给createTest节点创建监听,并返回stat,stat为空则表示当前节点不存在
// Stat stat = zooKeeper.exists("/createTest",true);
//或者getData给createTest节点创建监听
zooKeeper.getData("/createTest",true, stat);
//修改节点 -1表示不用管版本号
zooKeeper.setData("/createTest","test2".getBytes(), -1);
//这里需要让main线程sleep一下或者await一下,如果不sleep会导致main执行完成,但是服务端向客户端发送的watch通知还没到达
// Thread.sleep(2000);
countDownLatch2.await();
//创建子节点 子节点与上面类似 只有一点需要注意,就是父节点必须是持久化节点不能是临时节点 。临时节点不能有子节点。
}
public void process(WatchedEvent watchedEvent) {
//如果当前的连接状态是连接成功的,那么通过计数器去控制
if(watchedEvent.getState() == Event.KeeperState.SyncConnected){
//第一次进来的连接状态
if(Event.EventType.None==watchedEvent.getType()&&null==watchedEvent.getPath()){
countDownLatch.countDown();
System.out.println(watchedEvent.getState()+"-->"+watchedEvent.getType());
}
//创建子节点的时候会触发
else if(watchedEvent.getType()== Event.EventType.NodeDataChanged){
try {
//通过路径获取数据将数据存储在stat中,true表示再注册一次通知,因为通知是一次失效的
byte[] data = zooKeeper.getData(watchedEvent.getPath(),true,stat);
System.out.println("stat:"+stat);
System.out.println("节点数据变更路径:"+watchedEvent.getPath()+"->节点的值:"+new String(data));
countDownLatch2.countDown();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
删除节点与监听:
public class ApiOperatorDemo implements Watcher{
//连接地址及端口号
private final static String CONNECTSTRING="192.168.74.131:2181,192.168.74.132:2181,192.168.74.133:2181";
//并发包工具类
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static CountDownLatch countDownLatch2 = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
//节点状态信息
private static Stat stat = new Stat();
public static void main(String[] args) throws Exception{
zooKeeper = new ZooKeeper(CONNECTSTRING, 10000, new ApiOperatorDemo());
countDownLatch.await();
//使用exist给createTest节点创建监听,并返回stat,stat为空则表示当前节点不存在
// Stat stat = zooKeeper.exists("/createTest",true);
//或者getData给createTest节点创建监听
zooKeeper.getData("/createTest",true, stat);
//删除节点
zooKeeper.delete("/createTest", -1);
//这里需要让main线程sleep一下或者await一下,如果不sleep会导致main执行完成,但是服务端向客户端发送的watch通知还没到达
// Thread.sleep(2000);
countDownLatch2.await();
//创建子节点 子节点与上面类似 只有一点需要注意,就是父节点必须是持久化节点不能是临时节点 。临时节点不能有子节点。
}
public void process(WatchedEvent watchedEvent) {
//如果当前的连接状态是连接成功的,那么通过计数器去控制
if(watchedEvent.getState() == Event.KeeperState.SyncConnected){
//第一次进来的连接状态
if(Event.EventType.None==watchedEvent.getType()&&null==watchedEvent.getPath()){
countDownLatch.countDown();
System.out.println(watchedEvent.getState()+"-->"+watchedEvent.getType());
}
//删除子节点的时候会触发
else if(watchedEvent.getType()== Event.EventType.NodeDeleted){
System.out.println("节点删除路径:"+watchedEvent.getPath());
countDownLatch2.countDown();
}
}
}
}
运行结果:
zkClient的使用:
创建会话: 比原生的简单多了
public class SessionDemo {
private final static String CONNECTSTRING="192.168.74.131:2181,192.168.74.132:2181,192.168.74.133:2181";
public static void main(String[] args) {
ZkClient zkClient = new ZkClient(CONNECTSTRING,4000);
System.out.println(zkClient+"--->SUCCESS");
}
}
基本操作:zkClient递归创建父节点,监控节点,修改节点:
public class ZKClientApiOperatorDemo {
private final static String CONNECTSTRING="192.168.74.131:2181,192.168.74.132:2181,192.168.74.133:2181";
public static void main(String[] args) throws Exception {
ZkClient zkClient = new ZkClient(CONNECTSTRING,4000);
System.out.println(zkClient+"--->SUCCESS");
//zkCLient提供递归创建父节点的功能
zkClient.createPersistent("/zkclient/zkclient1/zkclient1-1/zkclient1-1-1",true);
//获取子节点
List<String> children = zkClient.getChildren("/zkclient");
System.out.println("children:"+children);
//watcher
zkClient.subscribeDataChanges("/zkclient",new IZkDataListener() {
public void handleDataDeleted(String dataPath) throws Exception {
// TODO Auto-generated method stub
}
public void handleDataChange(String dataPath, Object data) throws Exception {
// TODO Auto-generated method stub
System.out.println("节点名称:"+dataPath+"->节点修改后的值"+data);
}
});
zkClient.writeData("/zkclient", "123");
TimeUnit.SECONDS.sleep(2);
}
}