Java操作zookeeper
Java操作zookeeper总共有三种方式:
1.原生的Java API
2.zkclient
3.curator
第一种实现代码:
pom.xml
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.8</version>
</dependency>
示例的java代码如下:
package zook; import java.io.IOException;
import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs; public class App { public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
String connStr = "192.168.126.128:2181";
CountDownLatch countDown = new CountDownLatch(1); Watcher watcher=new Watcher() {
@Override
public void process(WatchedEvent event) {
if (event.getState() == KeeperState.SyncConnected) {
System.err.println("eventType:"+event.getType());
if(event.getType()==Event.EventType.None){
countDown.countDown();
}else if(event.getType()==Event.EventType.NodeCreated){
System.out.println("listen:节点创建");
}else if(event.getType()==Event.EventType.NodeChildrenChanged){
System.out.println("listen:子节点修改");
}
}
}
}; ZooKeeper zookeeper = new ZooKeeper(connStr, 5000,watcher );
countDown.await(); //注册监听,每次都要重新注册,否则监听不到
zookeeper.exists("/top/jinyong", watcher); // 创建节点
String result = zookeeper.create("/top/jinyong", "一生一世".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(result); Thread.sleep(10); // 获取节点
byte[] bs = zookeeper.getData("/top/jinyong", true, null);
result = new String(bs);
System.out.println("创建节点后的数据是:" + result); // 修改节点
zookeeper.setData("/top/jinyong", "I love you".getBytes(), -1); Thread.sleep(10); bs = zookeeper.getData("/top/jinyong", true, null);
result = new String(bs);
System.out.println("修改节点后的数据是:" + result); // 删除节点
zookeeper.delete("/top/jinyong", -1);
System.out.println("节点删除成功");
} }
说明:
1.会话连接是异步的,需要自己去处理。此处用的CountDownLatch
2.Watch需要重复注册,不然就不能生效,比如开始的zookeeper.exists("/top/jinyong", watcher);就是为了注册监听
3.开发的复杂性还是比较高的
4.不支持多节点删除和创建。需要自己去递归。后面有一个关于递归的示例。
第二种实现:
pom.xml
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
示例的Java代码如下:
package zook; import java.util.List; import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.IZkStateListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.Watcher.Event.KeeperState; public class Client { public static void main(String[] args) throws InterruptedException {
String connStr = "192.168.126.128:2181";
ZkClient zk = new ZkClient(connStr); // 注册【数据】事件
zk.subscribeDataChanges("/top/zhuzhu", new IZkDataListener() { @Override
public void handleDataDeleted(String arg0) throws Exception {
System.err.println("数据删除:" + arg0); } @Override
public void handleDataChange(String arg0, Object arg1) throws Exception {
System.err.println("数据修改:" + arg0 + "------" + arg1); }
}); zk.subscribeChildChanges("/top", new IZkChildListener() { @Override
public void handleChildChange(String arg0, List<String> arg1) throws Exception {
System.err.println("子节点发生变化:" + arg0);
arg1.forEach(f -> {
System.out.println("content:" + f);
});
}
}); List<String> list = zk.getChildren("/");
list.forEach(e -> {
System.out.println(e);
}); String res = zk.create("/top/zhuzhu", "I love you", CreateMode.PERSISTENT);
System.out.println("创建节点/top/zhuzhu成功:" + res); zk.writeData("/top/zhuzhu", "forerver");
System.out.println("修改节点/top/zhuzhu数据成功"); res = zk.readData("/top/zhuzhu");
System.out.println("节点数据:" + res); Thread.sleep(1000); zk.delete("/top/zhuzhu");
System.out.println("删除节点/top/zhuzhu成功"); Thread.sleep(1000); System.out.println("------------------------------------------------"); for (int i = 0; i < 10; i++) {
zk.create("/top/zhuzhu", "I love you", CreateMode.PERSISTENT);
Thread.sleep(1000);
zk.delete("/top/zhuzhu");
Thread.sleep(1000);
} } }
说明:
1.subscribe开头的为注册监听的一些方法
2.addAuthInfo和setAcl为权限相关控制
3.普通使用这种方式还是值得推荐的
第三种实现:
pom.xml
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.11.0</version>
</dependency>
示例的Java代码如下:
package zook; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
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.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat; public class Curator { public static void main(String[] args) throws Exception {
String connStr = "192.168.23.24:2181";
CuratorFramework cur=CuratorFrameworkFactory.builder()
.connectString(connStr)
.connectionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(1000,3))
.build();
cur.start();//连接 //创建监听
PathChildrenCache cache=new PathChildrenCache(cur,"/top",true);
cache.start();
cache.rebuild();
cache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework framwork, PathChildrenCacheEvent event) throws Exception {
System.err.println("节点发生变化:"+event.getType());
}
}); Stat stat=cur.checkExists().forPath("/top/zhuzhu");
if(stat!=null){
System.out.println("【/top/zhuzhu】节点存在,直接删除");
cur.delete().forPath("/top/zhuzhu");
}
cur.delete().forPath("/top/zhuzhu"); System.in.read(); System.out.println("准备创建【/top/zhuzhu】");
cur.create().withMode(CreateMode.PERSISTENT)
.forPath("/top/zhuzhu", "love forever".getBytes());
System.out.println("节点【/top/zhuzhu】创建成功"); Thread.sleep(1000); byte[] bs=cur.getData().forPath("/top/zhuzhu");
System.out.println("数据:"+new String(bs)); Thread.sleep(1000); cur.delete().forPath("/top/zhuzhu"); Thread.sleep(1000); } /**
* 三种watcher来做节点的监听
* pathcache 监视一个路径下子节点的创建、删除、节点数据更新
* NodeCache 监视一个节点的创建、更新、删除
* TreeCache pathcaceh+nodecache 的合体(监视路径下的创建、更新、删除事件),
* 缓存路径下的所有子节点的数据
*/ public static void main1(String[] args) throws Exception {
String connStr = "192.168.23.24:2181";
CuratorFramework curatorFramework=CuratorFrameworkFactory.builder()
.connectString(connStr)
.connectionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(1000,3))
.build();
curatorFramework.start(); /**
* 节点变化NodeCache
*/
/* NodeCache cache=new NodeCache(curatorFramework,"/curator",false);
cache.start(true); cache.getListenable().addListener(()-> System.out.println("节点数据发生变化,变化后的结果" +
":"+new String(cache.getCurrentData().getData()))); curatorFramework.setData().forPath("/curator","菲菲".getBytes());*/ /**
* PatchChildrenCache
*/ PathChildrenCache cache=new PathChildrenCache(curatorFramework,"/event",true);
cache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
cache.rebuild();
// Normal / BUILD_INITIAL_CACHE /POST_INITIALIZED_EVENT cache.getListenable().addListener((curatorFramework1,pathChildrenCacheEvent)->{
switch (pathChildrenCacheEvent.getType()){
case CHILD_ADDED:
System.out.println("增加子节点");
break;
case CHILD_REMOVED:
System.out.println("删除子节点");
break;
case CHILD_UPDATED:
System.out.println("更新子节点");
break;
default:break;
}
}); // curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/event","event".getBytes());
// TimeUnit.SECONDS.sleep(1);
// System.out.println("1");
// curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/event/event1","1".getBytes());
// TimeUnit.SECONDS.sleep(1);
// System.out.println("2");
//
// curatorFramework.setData().forPath("/event/event1","222".getBytes());
// TimeUnit.SECONDS.sleep(1);
// System.out.println("3"); curatorFramework.delete().forPath("/event/event1");
System.out.println("4"); System.in.read(); } }
说明:
1.支持事务
2.支持Flush写法
3.开始测试多次程序启动就执行删除节点,而监听的结果确实新增,后来加了cache.rebuild();代码就没问题了。跟源码,在cache.start()里面有一个构造函数也是调用了rebuild方法的。
4.功能还是比较强大的。高级功能都会用到这种方式
最后贴一个原生API的递归操作方式:
package zook; import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs; public class ZookManager {
ZooKeeper zookeeper = null; public ZookManager(String connStr) throws IOException, InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
zookeeper = new ZooKeeper(connStr, 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
if (event.getType() == EventType.None) {
if (event.getState() == KeeperState.SyncConnected) {
latch.countDown();
} else {
System.out.println("连接失败.");
latch.countDown();
}
}
} });
latch.await();
} /** 创建节点,不存在父节点将新增,如果节点已经存在将抛出异常 **/
public String create(String path, String val) throws KeeperException, InterruptedException {
if (!checkPath(path)) {
return "";
} String p = getParentPath(path);
cycleCreate(p); String url = zookeeper.create(path, val.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
return url;
} /** 设置节点的数据,如果节点不存在将新增该节点 **/
public Stat setData(String path, String val) throws KeeperException, InterruptedException {
if (!checkPath(path)) {
return null;
} cycleCreate(path);
return zookeeper.setData(path, val.getBytes(), -1);
} /** 删除节点,如果存在子节点将递归删除
* @throws InterruptedException
* @throws KeeperException **/
public void delete(String path) throws KeeperException, InterruptedException {
if (!checkPath(path)) {
return;
} List<String> chidren = zookeeper.getChildren(path, false);
for (String p : chidren) {
delete(path + "/" + p);
}
zookeeper.delete(path, -1);
} private void cycleCreate(String path) throws KeeperException, InterruptedException {
Stat stat = zookeeper.exists(path, null);
if (stat == null) {
String p = getParentPath(path);
cycleCreate(p);// 递归
// 创建
zookeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
} /**
* 检查目录是否正确
* @param path
* @return
*/
private boolean checkPath(String path) {
if (!path.startsWith("/")) {
System.err.println("路径必须以/开头:" + path);
return false;
}
if (path.endsWith("/")) {
System.err.println("路径不能以/结尾:" + path);
return false;
}
if (path.contains("//")) {
System.err.println("路径格式不对,存在连续的/:" + path);
return false;
}
if (path.equals("/")) {
System.err.println("路径格式不对,只有一个/:" + path);
return false;
}
return true;
} /**
* 获得父级目录
* @param path /root/abc
* @return
*/
private String getParentPath(String path) {
int index = path.lastIndexOf("/");
return path.substring(0, index);
} public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZookManager zoo = new ZookManager("192.168.23.24:2181");
zoo.setData("/top/enjoy/abc", "abc");
zoo.setData("/top/enjoy/bbb", "bbb");
zoo.setData("/top/enjoy/ccc", "ccc");
System.out.println("成功新增");
zoo.delete("/top/enjoy");
System.out.println("成功删除");
}
}
Java操作zookeeper的更多相关文章
- java 操作zookeeper
java 操作zookeeper(一) 首先要使用java操作zookeeper,zookeeper的javaclient 使我们更轻松的去对zookeeper进行各种操作,我们引入zookeeper ...
- zookeeper(三):java操作zookeeper
引入jar包 首先要使用java操作zookeeper,zookeeper的javaclient 使我们更轻松的去对zookeeper进行各种操作,我们引入zookeeper-3.4.5.jar 和 ...
- Java 使用ZkClient操作Zookeeper
目录 ZkClient介绍 导入jar包依赖 简单使用样例 ZkClient介绍 因为Zookeeper API比较复杂,使用并不方便,所以出现了ZkClient,ZkClient对Zookeeper ...
- Java代码操作zookeeper
.personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...
- Zookeeper--java操作zookeeper
如果是使用java操作zookeeper,zookeeper的javaclient 使我们更轻松的去对zookeeper进行各种操作,我们引入zookeeper-3.4.5.jar 和 zkclien ...
- Zookeeper入门(七)之Java连接Zookeeper
Java操作Zookeeper很简单,但是前提要把包导对. 关于Zookeeper的Linux环境搭建可以参考我的这篇博客:Linux环境下Zookeeper安装 下面进入正题: 一.导入依赖 < ...
- Java curator操作zookeeper获取kafka
Java curator操作zookeeper获取kafka Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更 ...
- Hbase深入学习(六) Java操作HBase
Hbase深入学习(六) ―― Java操作HBase 本文讲述如何用hbase shell命令和hbase java api对hbase服务器进行操作. 先看以下读取一行记录hbase是如何进行工作 ...
- Java操作hbase总结
用过以后,总得写个总结,不然,就忘喽. 一.寻找操作的jar包. java操作hbase,首先要考虑到使用hbase的jar包. 因为咱装的是CDH5,比较方便,使用SecureCRT工具,远程连接到 ...
随机推荐
- 识别简单的答题卡(Bubble sheet multiple choice scanner and test grader using OMR, Python and OpenCV——jsxyhelu重新整编)
该博客转自www.pyimagesearch.com,进行了相关修改补充. Over the past few months I've gotten quite the number of reque ...
- JavaScript中this的用法 及 如何改变this的指向
要懂得JavaScript中this的用法,首先需要知道,JavaScript中的作用域相关知识. var fun = function(){ var flag = 1; console.log(fl ...
- linux tmux 工具使用 tmux.conf 文件
set -g prefix ^a unbind ^b bind a send-prefix unbind '"' bind - splitw -v unbind % bind \ split ...
- iOS开发 -------- UITableView的编辑
一 核心API Class: UITableView Delegate: UITableViewDataSource, UITableViewDelegate 涉及到的API: 插入和删除 1 /** ...
- FireMonkey 源码学习(3)
五.TTextLayoutNG 在FMX.TextLayout.GPU.pas文件中,实现了几个基础功能,其中: (1)渲染单元 在TextLayout中,每一批同字体和颜色的1~n个字符,组成一个最 ...
- C# Math类简介运用
总结了一下几个常用的Math类 /* ######### ############ ############# ## ########### ### ###### ##### ### ####### ...
- word2010使用记录
安装时提示: installer无法更新被保护的一个或多个文件, 解决方法是: 将三个dll文件,放在 c:\program files\common files\ms shared\web serv ...
- Docker 使用Dockerfile构建tomcat镜像
Dockerfile概念: 镜像的定制实际上就是定制每一层所添加的配置.文件.如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那么之前提及的无法重复的问题. ...
- P2221 [HAOI2012]高速公路
思路 考虑每一条边的贡献,然后推式子 \[ \begin{align}&\sum_{i}V_i\times(R-i+1)\times(i-L+1)\\=&\sum_{i}V_i\lef ...
- Vue学习四:v-if及v-show指令使用方法
本文为博主原创,未经允许不得转载: <!DOCTYPE html> <html lang="zh"> <head> <meta http- ...