Zookeeper说明
创建节点方法
create:提供了两套创建节点的方法,同步和异步创建节点方式。
同步方式:
参数1,节点路径(名称) : InodeName (不允许递归创建节点,也就是说在父节点不存在
的情况下,不允许创建子节点)
参数2,节点内容: 要求类型是字节数组(也就是说,不支持序列化方式,如果需要实现序
列化,可使用java相关序列化框架,如Hessian、Kryo框架)
参數3,节点权限: 使用Ids.OPEN_ACL_UNSAFE开放权限即可。(这个参数一般在权展
没有太高要求的场景下,没必要关注)
参数4,节点类型: 创建节点的类型: CreateMode,提供四种节点类型
PERSISTENT 持久化节点
PERSISTENT_SEQUENTIAL 顺序自动编号持久化节点,这种节点会根据当前已存在的节点数自动加 1
EPHEMERAL 临时节点, 客户端session超时这类节点就会被自动删除
EPHEMERAL_SEQUENTIAL 临时自动编号节点
修改节点方法
setData:
参数1,节点路径(名称) ;
参数2,节点内容;
参数3(version),version参数指定要更新的数据的版本, 如果version和真实的版本不同, 更新操作将失败. 指定version为-1则忽略版本检查
Maven依赖信息
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
Watcher
在ZooKeeper中,接口类Watcher用于表示一个标准的事件处理器,其定义了事件通知相关的逻辑,包含KeeperState和EventType两个枚举类,分别代表了通知状态和事件类型,同时定义了事件的回调方法:process(WatchedEvent event)。
什么是Watcher接口
同一个事件类型在不同的通知状态中代表的含义有所不同,下表列举了常见的通知状态和事件类型:
回调方法process()
process方法是Watcher接口中的一个回调方法,当ZooKeeper向客户端发送一个Watcher事件通知时,客户端就会对相应的process方法进行回调,从而实现对事件的处理。
process方法的定义如下:
abstract public void process(WatchedEvent event);
这个回调方法的定义非常简单,我们重点看下方法的参数定义:WatchedEvent。
WatchedEvent包含了每一个事件的三个基本属性:
通知状态(keeperState),事件类型(EventType)和节点路径(path),其数据结构如上图所示。ZooKeeper使用WatchedEvent对象来封装服务端事件并传递给Watcher,从而方便回调方法process对服务端事件进行处理。
代码实现
package com.wangys.test;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* <p>Project: java-zookeeper</p>
* <p>ClassName: BaseTest.java</p>
* <p>Description: </p>
* <p>CreateDate: 2018-09-03 上午11:47</p>
* <p>Author: 王永圣</p>
* <p>Version: 1.0.0</p>
* <p>Copyright: Copyright(c) 2018</p>
*/
public class BaseTest implements Watcher{
//连接地址
private static final String ADDRESS = "127.0.0.1:2181";
//session会话
private static final Integer SESSION_TIMEOUT = 2000;
//信号量,阻塞程序执行,用户必须等待zookeeper连接成功,发送成功信号
private static final CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(1);
private ZooKeeper zk;
/**
* 创建连接
* @param address
* @param sessionTimeout
*/
public void createConnection(String address,Integer sessionTimeout){
try {
zk = new ZooKeeper(address,sessionTimeout,this);
System.out.println("###zookeeper启动连接服务器###");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 事件处理
* @param watchedEvent
*/
@Override
public void process(WatchedEvent watchedEvent) {
//1、获取事件状态
Event.KeeperState state = watchedEvent.getState();
//2、获取事件类型
Event.EventType type = watchedEvent.getType();
//获取节点地址
String path = watchedEvent.getPath();
//3、判断是否连接
if (Event.KeeperState.SyncConnected == state) {
//4、判断类型
if (Event.EventType.None == type) {
/*try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
COUNT_DOWN_LATCH.countDown();
System.out.println("###zookeeper建立连接成功###");
} else if (Event.EventType.NodeCreated == type) {
System.out.println("###Watcher监听的对应数据节点被创建###, 当前新增节点:"+path);
} else if (Event.EventType.NodeDataChanged == type) {
System.out.println("###Watcher监听的对应数据节点的数据内容发生变更###, 当前节点:"+path+",被修改...");
} else if (Event.EventType.NodeChildrenChanged == type) {
System.out.println("###Wather监听的对应数据节点的子节点列表发生变更###, 当前子节点:"+path+",被修改...");
} else if (Event.EventType.NodeDeleted == type) {
System.out.println("###Watcher监听的对应数据节点被删除###, 当前节点:"+path+",被删除...");
}
}
}
/**
* 创建持久化节点
* @param path
* @param data
*/
public boolean createNode(String path, String data){
try {
this.exists(path,true);
//阻塞,当等于0的时候释放
COUNT_DOWN_LATCH.await();
zk.create(path,data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
System.out.println("###新增节点信息path:"+path+" data:"+data);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 修改持久化节点
* @param path
* @param data
*/
public boolean updateNode(String path, String data){
try {
this.exists(path,true);
//阻塞,当等于0的时候释放
COUNT_DOWN_LATCH.await();
//zk的数据版本是从0开始计数的。如果客户端传入的是-1,则表示zk服务器需要基于最新的数据进行更新。如果对zk的数据节点的更新操作没有原子性要求则可以使用-1.
//version参数指定要更新的数据的版本, 如果version和真实的版本不同, 更新操作将失败. 指定version为-1则忽略版本检查
zk.setData(path,data.getBytes(),-1);
System.out.println("###修改节点信息path:"+path+" data:"+data);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除持久化节点
* @param path
*/
public boolean deleteNode(String path){
try {
this.exists(path,true);
//阻塞,当等于0的时候释放
COUNT_DOWN_LATCH.await();
//version参数指定要更新的数据的版本, 如果version和真实的版本不同, 更新操作将失败. 指定version为-1则忽略版本检查
zk.delete(path,-1);
System.out.println("###删除节点信息path:"+path);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 判断指定节点是否存在
* @param path
* @param needWatch
* @return
*/
public Stat exists(String path, boolean needWatch){
try {
return this.zk.exists(path,needWatch);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 关闭服务
*/
public void close(){
try {
if(zk!=null){
System.out.println("###zookeeper服务已关闭");
zk.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args){
BaseTest test = new BaseTest();
test.createConnection(ADDRESS,SESSION_TIMEOUT);
// test.createNode("/yswKnight/wangys","wangYongsheng");
// test.updateNode("/yswKnight/wangys","dasheng");
test.deleteNode("/yswKnight/wangys");
test.close();
}
}