1. 导入依赖
注意导入的zookeeper包的版本必须和虚拟机安装的zookeeper版本一致。
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
2. API使用
2.1 创建zookeeper对象
//通过CountDownLatch,实现异步的同步问题,使zookeeper创建成功在继续往下执行
final CountDownLatch downLatch = new CountDownLatch(1);
//异步创建zookeeper对象,不堵塞线程。
//watcher为回调函数
ZooKeeper zooKeeper = new ZooKeeper("192.168.45.27:2181,192.168.45.28:2181,192.168.45.29:2181,192.168.45.30:2181/test", //zookeeper集群节点信息
3000, //客户端断开连接,zookeeper保存连接session的时间
new Watcher() { //默认的watcher回调函数,session级别的。watcher回调,只发生在产生事件时。只有get和exist存在watch监听事件,其他操作都是事件的产生者
@Override
public void process(WatchedEvent watchedEvent) {
String path = watchedEvent.getPath();
System.out.println(path);
System.out.println(watchedEvent.toString());
switch (watchedEvent.getState()) {
case Unknown:
break;
case Disconnected:
break;
case NoSyncConnected:
break;
case SyncConnected:
System.out.println("initWatcher:Connected!");
downLatch.countDown();
break;
case AuthFailed:
break;
case ConnectedReadOnly:
break;
case SaslAuthenticated:
break;
case Expired:
break;
}
switch (watchedEvent.getType()) {
case None:
break;
case NodeCreated:
break;
case NodeDeleted:
break;
case NodeDataChanged:
break;
case NodeChildrenChanged:
break;
}
}
});
downLatch.await(); //等待zookeeper异步创建成功在继续执行。
ZooKeeper.States state = zooKeeper.getState();
switch (state) {
case CONNECTING:
System.out.println("zk.states.connecting!!");
break;
case ASSOCIATING:
break;
case CONNECTED:
System.out.println("zk.states.connected!!");
break;
case CONNECTEDREADONLY:
break;
case CLOSED:
break;
case AUTH_FAILED:
break;
case NOT_CONNECTED:
break;
}
2.2 创建节点
同步方式:
public String create(String path, byte[] data, List<ACL> acl, CreateMode createMode)
-
path:创建节点的路径
-
byte[] data 节点信息的字节数组
-
acl
public interface Ids { Id ANYONE_ID_UNSAFE = new Id("world", "anyone"); Id AUTH_IDS = new Id("auth", ""); ArrayList<ACL> OPEN_ACL_UNSAFE = new ArrayList(Collections.singletonList(new ACL(31, ANYONE_ID_UNSAFE))); ArrayList<ACL> CREATOR_ALL_ACL = new ArrayList(Collections.singletonList(new ACL(31, AUTH_IDS))); ArrayList<ACL> READ_ACL_UNSAFE = new ArrayList(Collections.singletonList(new ACL(1, ANYONE_ID_UNSAFE))); }
-
CreateMode createMode创建节点的模式
public enum CreateMode { PERSISTENT(0, false, false), //持久节点 PERSISTENT_SEQUENTIAL(2, false, true), //持久序列化节点 EPHEMERAL(1, true, false), //临时节点 EPHEMERAL_SEQUENTIAL(3, true, true); //临时序列化节点
异步创建方式:
public void create(String path, byte[] data, List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx) {
StringCallback:表示创建成功的回调函数
Object ctx:上下文对象
2.3 获取数据
同步方式一:
public byte[] getData(String path, Watcher watcher, Stat stat)
String path:节点路径
Watcher watcher:监听节点事件,如果节点产生事件,回调这个函数,只会回调一次
Stat stat:存储节点元数据信息
返回值:节点数据的字节数组
同步方式二:
public byte[] getData(String path, boolean watch, Stat stat)
boolean watch:如果为true,就表示使用zookeeper对象参数中的默认watcher监听。为false就表示不进行事件监听。
异步方式一:
public void getData(String path, Watcher watcher, DataCallback cb, Object ctx)
DataCallback cb:获取到数据后的回调函数
Object ctx:上下文对象
异步方式二:
public void getData(String path, boolean watch, DataCallback cb, Object ctx)
2.4 修改节点信息
同步方式:
public Stat setData(String path, byte[] data, int version)
int version:数据的版本
异步方式:
public void setData(String path, byte[] data, int version, StatCallback cb, Object ctx)
2.5 节点是否存在
方式一:
public Stat exists(String path, Watcher watcher)
方式二:
public Stat exists(String path, boolean watch)
方式三:
public void exists(String path, Watcher watcher, StatCallback cb, Object ctx)
方式四:
public void exists(String path, boolean watch, StatCallback cb, Object ctx)
3. 示例
案例:zookeeper中某个目录节点保存了多台服务的配置文件。多台服务需要根据zookeeper中的配置文件进行相关配置。zookeeper保存的配置文件可以进行增删改操作,相应的多台服务需要及时的进行配置文件同步。
获取zookeeper连接对象工具类
public class ZkUtil {
private static ZooKeeper zk;
private static String path = "192.168.45.27:2181,192.168.45.28:2181,192.168.45.29:2181/test";
private static CountDownLatch countDownLatch = new CountDownLatch(1);
public static ZooKeeper getZk(){
DefaultWatcher defaultWatcher = new DefaultWatcher();
defaultWatcher.setCountDownLatch(countDownLatch);
try {
zk = new ZooKeeper(path,300,defaultWatcher);
countDownLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
return zk;
}
}
public class DefaultWatcher implements Watcher {
private CountDownLatch countDownLatch;
public CountDownLatch getCountDownLatch() {
return countDownLatch;
}
public void setCountDownLatch(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void process(WatchedEvent watchedEvent) {
switch (watchedEvent.getState()) {
case Unknown:
break;
case Disconnected:
break;
case NoSyncConnected:
break;
case SyncConnected:
System.out.println("zookeeper连接建立!!!!");
countDownLatch.countDown();
break;
case AuthFailed:
break;
case ConnectedReadOnly:
break;
case SaslAuthenticated:
break;
case Expired:
break;
}
}
watcher封装类:
public class GetExistWatcher implements Watcher,AsyncCallback.StatCallback,AsyncCallback.DataCallback {
private ZooKeeper zk;
private StringConf conf;
private CountDownLatch latch = new CountDownLatch(1);
public ZooKeeper getZk() {
return zk;
}
public void setZk(ZooKeeper zk) {
this.zk = zk;
}
public StringConf getConf() {
return conf;
}
public void setConf(StringConf conf) {
this.conf = conf;
}
public void aWait(){
try {
zk.exists("/appConf",this,this,"aaa");
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* getData时调用的回调函数
* @param i
* @param s
* @param o
* @param bytes
* @param stat
*/
@Override
public void processResult(int i, String s, Object o, byte[] bytes, Stat stat) {
if(bytes != null){
conf.setConf(new String(bytes));
latch.countDown();
}
}
/**
* exist时调用的回调函数
* @param i
* @param s
* @param o
* @param stat
*/
@Override
public void processResult(int i, String s, Object o, Stat stat) {
if(stat != null){
zk.getData("/appConf",this,this,"");
}
}
/**
* watcher监听事件
* @param watchedEvent
*/
@Override
public void process(WatchedEvent watchedEvent) {
switch (watchedEvent.getType()) {
case None:
break;
case NodeCreated:
zk.getData("/appConf",this,this,"");
break;
case NodeDeleted:
conf.setConf("");
latch = new CountDownLatch(1);
break;
case NodeDataChanged:
zk.getData("/appConf",this,this,"");
break;
case NodeChildrenChanged:
break;
}
}
}
测试类:
public class TestConf {
private ZooKeeper zk;
@Before
public void init(){
zk = ZkUtil.getZk();
}
@After
public void destory(){
try {
zk.close();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void testConf(){
GetExistWatcher watcher = new GetExistWatcher();
StringConf strConf = new StringConf();
watcher.setZk(zk);
watcher.setConf(strConf);
watcher.aWait();
while (true){
if("".equals(strConf.getConf())){
System.out.println("节点被删除了!!!!");
watcher.aWait();
}else {
System.out.println(strConf.getConf());
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
配置文件类:
public class StringConf {
private String conf;
public String getConf() {
return conf;
}
public void setConf(String conf) {
this.conf = conf;
}
}