zkClient是一个遵循Apache 2.0 License的开源项目,比起zookeeper的源生API有如下两个优势
1,当zookeeper client的session超时后,会自动重连
2, 将原生的一次性watcher封装成持久性订阅,更加简单易用
一,通过源码构建zkClient.jar
首先从Github下载zkClient源码,打开Eclipse,选则Window -> Open Perspective -> Other... -> Git
进入Git视图后选则Clone Git Repository,在URI中输入zkClient的远程库地址:https://github.com/sgroschupf/zkclient
只有一个master分支
选则源代码的本地存放路径
之后等待代码下载完成即可,下载下来的源码并不是一个Java工程,所以Import all existing projects after clone finishes选项并没有生效
创建一个名为zkClient的Java工程,并将zkClient的源码拷贝至该工程中,导入zkClient的依赖jar即可
使用该工程导出zkClient.jar即可
二,zkClient的使用方式
1,创建节点
package com.sean;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;
public class Test {
public static void main(String[] args) throws Exception {
ZkClient zkClient = new ZkClient("192.168.137.128:2181");
// 创建持久化节点,连接关闭后节点依然存在
zkClient.createPersistent("/sean");
// 创建非持久化节点,连接关闭后节点将被删除
zkClient.create("/sean/child", "Just a test!", CreateMode.EPHEMERAL);
zkClient.close();
}
}
[zk: localhost:2181(CONNECTED) 6] ls /
[zookeeper, sean]
[zk: localhost:2181(CONNECTED) 7] ls /sean
[]
2,修改节点
package com.sean;
import org.I0Itec.zkclient.ZkClient;
public class Test {
public static void main(String[] args) throws Exception {
ZkClient zkClient = new ZkClient("192.168.137.128:2181");
zkClient.writeData("/sean", "wirte new data");
zkClient.close();
}
}
[zk: localhost:2181(CONNECTED) 23] get /sean
��twirte new data
cZxid = 0x15
ctime = Mon Sep 12 23:21:42 CST 2016
mZxid = 0x18
mtime = Mon Sep 12 23:23:03 CST 2016
pZxid = 0x15
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 21
numChildren = 0
3,判断节点是否存在
package com.sean;
import org.I0Itec.zkclient.ZkClient;
import org.apache.log4j.Logger;
public class Test {
public static Logger log = Logger.getLogger(Test.class);
public static void main(String[] args) {
ZkClient zkClient = new ZkClient("192.168.137.128:2181");
boolean flag = zkClient.exists("/sean");
log.info(flag);
}
}
4,查询节点
package com.sean;
import java.util.List;
import org.I0Itec.zkclient.ZkClient;
import org.apache.log4j.Logger;
public class Test {
public static Logger log = Logger.getLogger(Test.class);
public static void main(String[] args) {
ZkClient zkClient = new ZkClient("192.168.137.128:2181");
// 只会查询直接子节点,并不会递归查询到所有子节点
List<String> children = zkClient.getChildren("/");
for(String temp : children)
log.info(temp);
}
}
INFO[16-09-12 23:30:14][com.sean.Test] -> zookeeper
INFO[16-09-12 23:30:14][com.sean.Test] -> sean
5,删除节点
package com.sean;
import org.I0Itec.zkclient.ZkClient;
public class Test {
public static void main(String[] args) throws Exception {
ZkClient zkClient = new ZkClient("192.168.137.128:2181");
// 如果节点下还有子节点,则删除失败
zkClient.delete("/sean");
// 递归删除节点下的所有节点
// zkClient.deleteRecursive("/sean");
zkClient.close();
}
}
[zk: localhost:2181(CONNECTED) 24] get /sean
Node does not exist: /sean
6,订阅
package com.sean;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;
import org.apache.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import com.sean.listener.ChildChangeListener;
public class ClusterMonitor {
private Logger log = Logger.getLogger(ClusterMonitor.class);
private ZkClient zkClient;
public volatile boolean flag = false;
// public static String location = "192.168.137.128:2181";
public final static String location = "192.168.52.129:2181";
public final static String rootPath = "/servers";
public static Map<String, String> serverIps =
new HashMap<String, String>();
public void startup(){
if(flag){
log.error("Cluster monitor is already started.");
}else{
zkClient = new ZkClient(location,
5000, 5000, new SerializableSerializer());
if(zkClient.exists(rootPath))
zkClient.deleteRecursive(rootPath);
zkClient.create(rootPath, "Server List", CreateMode.PERSISTENT);
List<String> servers = zkClient.getChildren(rootPath);
if(servers != null && servers.size() > 0){
for(String server : servers){
String serverIp = zkClient.readData(rootPath
+ "/" + server);
serverIps.put(serverIp, null);
}
}
log.info("server ip : " + serverIps.toString());
zkClient.subscribeChildChanges("/servers",
new ChildChangeListener(zkClient));
// zkClient.subscribeDataChanges("/servers", new DataChangeListener());
// zkClient.subscribeStateChanges(new StateChangeListener());
flag = true;
log.info("Cluster monitor is started.");
}
}
public void shutdown(){
zkClient.close();
log.info("Cluster monitor is stopped.");
}
public static void main(String[] args) throws Exception {
ClusterMonitor monitor = new ClusterMonitor();
monitor.startup();
Thread.sleep(5*60*1000);
}
}
package com.sean.listener;
import java.util.List;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.log4j.Logger;
import com.sean.ClusterMonitor;
public class ChildChangeListener implements IZkChildListener {
private Logger log = Logger.getLogger(ChildChangeListener.class);
private ZkClient zkClient;
public ChildChangeListener(ZkClient zkClient){
this.zkClient = zkClient;
}
@Override
public void handleChildChange(String parentPath, List<String> currentChilds)
throws Exception {
synchronized(zkClient){
ClusterMonitor.serverIps.clear();
if(currentChilds != null && currentChilds.size() > 0){
for(String child : currentChilds){
String serverIp = zkClient.readData(ClusterMonitor.rootPath
+ "/" + child);
ClusterMonitor.serverIps.put(serverIp, null);
}
}
}
log.info("server ip : " + ClusterMonitor.serverIps.toString());
}
}
log4j.rootLogger=info,logOutput
#log console out put
log4j.appender.logOutput=org.apache.log4j.ConsoleAppender
log4j.appender.logOutput.layout=org.apache.log4j.PatternLayout
log4j.appender.logOutput.layout.ConversionPattern=%m%n
测试代码如下:
package com.sean;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;
import org.apache.zookeeper.CreateMode;
public class Test {
// public static String location = "192.168.137.128:2181";
public final static String location = "192.168.52.129:2181";
public static void main(String[] args) {
ZkClient zkClient = new ZkClient(location,
5000, 5000, new SerializableSerializer());
zkClient.create("/servers/server1", "1.1.1.1", CreateMode.PERSISTENT);
zkClient.create("/servers/server2", "2.2.2.2", CreateMode.PERSISTENT);
zkClient.close();
}
}
测试结果如下:
server ip : {1.1.1.1=null, 2.2.2.2=null}