常用的zookeeper java客户端
-
zk原生api
-
zkclient
-
Apache curator
原生api的不足之处
-
超时重连,不支持自动,需要手动操作
-
Watch注册一次后会失效
-
不支持递归创建节点
Apache curator
-
Apache的开源项目
-
解决watcher的注册一次就失效的问题
-
Api更加简单易用
-
提供更多解决方案并实现简单:例如分布式锁
-
提供常用的zookeeper工具类
-
编程风格更爽,调用方便
1.会话的连接与关闭
搭建maven工程,建立curator与zkserver的连接
添加maven依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.11</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
</dependency>
建立curator与zkserver的连接
package com.zk.curator;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryUntilElapsed;
public class CuratorOperator {
public CuratorFramework client = null;
public static final String zkServePath = "192.168.119.129:2181";
/**
* 实例化zk客户端
*/
public CuratorOperator() {
/**
* 同步创建zk实例,原生api是异步的
*
* curator连接zookeeper的策略:ExponentialBackoffRetry
* baseSleepTimeMs:初始sleep的时间
* maxRetries:最大重试次数
* maxSleepMs:最大重试时间
* 推荐
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curaotr连接zookeeper的策略:RetryNTimes
* n:重试次数
* sleepMsBetweenRetries
* 推荐
*/
//RetryNTimes retryPolicy = new RetryNTimes(3, 5000);
/**
* curator连接zookeeper的策略:RetryOneTime
* sleepMsBetweenRetry:每次重试间隔的时间
*/
//RetryOneTime retryPolicy = new RetryOneTime(3000);
/**
* 永远重试,不推荐使用
*/
//RetryForever retryPolicy = new RetryForever(retryIntervalMs);
/**
* curator连接zookeeper的策略:RetryUntilElapsed
* maxElapsedTimes:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后就不在重试
*/
//RetryUntilElapsed retryPolicy = new RetryUntilElapsed(2000, 3000);
client = CuratorFrameworkFactory.builder()
.connectString(zkServePath)
.sessionTimeoutMs(10000).retryPolicy(retryPolicy)
.build();
client.start();
}
/**
* 关闭zk客户端连接
*/
public void closeZKClient(){
if(client != null){
this.client.close();
}
}
public static void main(String[] args) throws Exception {
//实例化
CuratorOperator cto = new CuratorOperator();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户端的状态:"+(isZkCuratorStarted?"连接中":"已关闭"));
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStared2 = cto.client.isStarted();
System.out.println("当前客户端的状态:"+(isZkCuratorStared2? "连接中":"已关闭"));
}
}
节点的增删改查
package com.zk.curator;
import java.util.List;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryUntilElapsed;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids
import org.apache.zookeeper.data.Stat;
public class CuratorOperator {
public CuratorFramework client = null;
public static final String zkServePath = "192.168.119.129:2181";
/**
* 实例化zk客户端
*/
public CuratorOperator() {
/**
* 同步创建zk实例,原生api是异步的
*
* curator连接zookeeper的策略:ExponentialBackoffRetry
* baseSleepTimeMs:初始sleep的时间
* maxRetries:最大重试次数
* maxSleepMs:最大重试时间
* 推荐
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curaotr连接zookeeper的策略:RetryNTimes
* n:重试次数
* sleepMsBetweenRetries
* 推荐
*/
//RetryNTimes retryPolicy = new RetryNTimes(3, 5000);
/**
* curator连接zookeeper的策略:RetryOneTime
* sleepMsBetweenRetry:每次重试间隔的时间
*/
//RetryOneTime retryPolicy = new RetryOneTime(3000);
/**
* 永远重试,不推荐使用
*/
//RetryForever retryPolicy = new RetryForever(retryIntervalMs);
/**
* curator连接zookeeper的策略:RetryUntilElapsed
* maxElapsedTimes:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后就不在重试
*/
//RetryUntilElapsed retryPolicy = new RetryUntilElapsed(2000, 3000);
client = CuratorFrameworkFactory.builder()
.connectString(zkServePath)
.sessionTimeoutMs(10000).retryPolicy(retryPolicy)
.namespace("workspace").build();
client.start();
}
/**
* 关闭zk客户端连接
*/
public void closeZKClient(){
if(client != null){
this.client.close();
}
}
public static void main(String[] args) throws Exception {
//实例化
CuratorOperator cto = new CuratorOperator();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户端的状态:"+(isZkCuratorStarted?"连接中":"已关闭"));
//创建节点
String nodePath = "/super/imooc";
// byte[] data = "superme".getBytes();
// cto.client.create().creatingParentsIfNeeded() //递归生成节点
// .withMode(CreateMode.PERSISTENT)
// .withACL(Ids.OPEN_ACL_UNSAFE)
// .forPath(nodePath,data);
//更新节点数据
// byte[] newData = "batman".getBytes();
// cto.client.setData()
// .withVersion(0)
// .forPath(nodePath,newData);
//删除节点
// cto.client.delete()
// .guaranteed()
// .deletingChildrenIfNeeded()
// .withVersion(1)
// .forPath(nodePath);
//读取节点
Stat stat = new Stat();
byte[] data = cto.client.getData().storingStatIn(stat).forPath(nodePath);
System.out.println("节点"+nodePath+"的数据为:"+new String(data));
System.out.println("改节点的版本号为:"+stat.getVersion());
//查询子节点
List<String> childNodes = cto.client.getChildren().forPath(nodePath);
System.out.println("开始打印子节点:");
for (String s : childNodes) {
System.out.println(s);
}
//判断节点是否存在,如果不存在则为空
Stat statExist = cto.client.checkExists().forPath(nodePath+"/abc");
System.out.println(statExist);
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStared2 = cto.client.isStarted();
System.out.println("当前客户端的状态:"+(isZkCuratorStared2? "连接中":"已关闭"));
}
}
watch与acl的相关操作
package com.zk.curator;
import java.util.List;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryUntilElapsed;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
/**
* curator操作zookeeper节点的增删改查
* @author 33193
*
*/
public class CuratorWatcher {
public CuratorFramework client = null;
public static final String zkServePath = "192.168.119.129:2181";
/**
* 实例化zk客户端
*/
public CuratorWatcher() {
/**
* 同步创建zk实例,原生api是异步的
* curator连接zookeeper的策略:ExponentialBackoffRetry
* baseSleepTimeMs:初始sleep的时间
* maxRetries:最大重试次数
* maxSleepMs:最大重试时间
* 推荐
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curaotr连接zookeeper的策略:RetryNTimes
* n:重试次数
* sleepMsBetweenRetries
* 推荐
*/
//RetryNTimes retryPolicy = new RetryNTimes(3, 5000);
/**
* curator连接zookeeper的策略:RetryOneTime
* sleepMsBetweenRetry:每次重试间隔的时间
*/
//RetryOneTime retryPolicy = new RetryOneTime(3000);
/**
* 永远重试,不推荐使用
*/
//RetryForever retryPolicy = new RetryForever(retryIntervalMs);
/**
* curator连接zookeeper的策略:RetryUntilElapsed
* maxElapsedTimes:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后就不在重试
*/
//RetryUntilElapsed retryPolicy = new RetryUntilElapsed(2000, 3000);
client = CuratorFrameworkFactory.builder()
.connectString(zkServePath)
.sessionTimeoutMs(10000).retryPolicy(retryPolicy)
.namespace("workspace").build();
client.start();
}
/**
* 关闭zk客户端连接
*/
public void closeZKClient(){
if(client != null){
this.client.close();
}
}
public static void main(String[] args) throws Exception {
//实例化
CuratorWatcher cto = new CuratorWatcher();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户端的状态:"+(isZkCuratorStarted?"连接中":"已关闭"));
String nodePath = "/super/imooc";
//watcher事件 当使用usingWatcher的时候,监听只会触发一次,监听完毕后就销毁
// cto.client.getData().usingWatcher(new MyCuratorWatcher()).forPath(nodePath);
// cto.client.getData().usingWatcher(new MyWatcher()).forPath(nodePath);
/**
* 一次注册N次监听
*/
//为节点添加watcher
//NodeCache:监听数据节点的变更,会触发事件
final NodeCache nodeCache = new NodeCache(cto.client, nodePath);
//buildInitial:初始化的时候获取node的值并且缓存
nodeCache.start(true);
if(nodeCache.getCurrentData() != null){
System.out.println("节点的初始化数据为:"+new String(nodeCache.getCurrentData().getData()));
}else{
System.out.println("节点初始化数据为空...");
}
//监听器
nodeCache.getListenable().addListener(new NodeCacheListener() {
public void nodeChanged() throws Exception {
String data = new String(nodeCache.getCurrentData().getData());
System.out.println("节点路径:"+nodeCache.getCurrentData().getPath()+"数据"+data);
}
});
//为子节点添加watcher
//PathChildrenCache:监听数据节点的增删改,会触发事件
String childNodePathCache = nodePath;
PathChildrenCache childrenCache = new PathChildrenCache(cto.client, childNodePathCache, true);
/**
* StartMode:初始化方式
* POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件
* NORMAL:异步初始化
* BUILD_INITIAL_CACHE:同步初始化
*/
childrenCache.start(StartMode.POST_INITIALIZED_EVENT);
List<ChildData> childDataList = childrenCache.getCurrentData();
System.out.println("当前数据节点的子节点数据列表:");
for (ChildData cd : childDataList) {
String childData = new String(cd.getData());
System.out.println(childData);
}
childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
if(event.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)){
System.out.println("子节点初始化ok");
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){
System.out.println("添加子节点:"+event.getData().getPath());
System.out.println("子节点数据:"+new String(event.getData().getData()));
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){
System.out.println("删除子节点:"+event.getData().getPath());
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
System.out.println("修改子节点:"+event.getData().getPath());
System.out.println("修改点数据:"+new String(event.getData().getData()));
}
}
});
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStared2 = cto.client.isStarted();
System.out.println("当前客户端的状态:"+(isZkCuratorStared2? "连接中":"已关闭"));
}
}