package com.zhouhao.zk;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
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.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
public class ZKTest {
private final String CONNECT_STR = "192.168.100.138:2181";
private final int TIMEOUT = 20000;
private ZooKeeper zookper;
public ZKTest() throws IOException {
/*
* 参数1:该参数是Zookeeper服务器的地址,形式127.1.1.1:8080,127.1.1.1:8088,127.1.1.1:8080
* /app,最后一种形式会以/app目录为根目录 参数2:超时时间 参数3:观察类
* 会话建立是异步的,构造函数一初始化就会立即返回,通常是在会话建立完成前就返回,
* 服务器节点任何状态的更改都会回调watcher,客户端会无序的选择一个服务器连接,客户端会一直连直到 服务器显示性的关闭。
*/
zookper = new ZooKeeper(CONNECT_STR, TIMEOUT, new Watcher() {
/**
* event包含了发生了哪些事,包括Zookeeper的状态,发生了事件的node的路径
*/
@Override
public void process(WatchedEvent event) {
log("PATH:" + event.getType());
}
});
}
/**
* 测试函数
*
* @throws KeeperException
* @throws InterruptedException
*/
public void test() throws KeeperException, InterruptedException {
/*
* 创建一个节点 参数1:节点路径,假如该节点父节点不存在或者父节点为Ephemeral会抛出KeeperException异常
* 该节点已经存在也会抛出那个异常。 参数2:节点数据(最多为1M)
* 参数3:该节点访问权限,Ids.OPEN_ACL_UNSAFE指的是所有人都可以访问
* 参数4:节点类型,PERSISTENT(持久的,只有显示删除才会删除).EPHEMERAL (会话关闭该节点自动删除,而且不能有子节点)
* SEQUENTIAL(连续的,该节点会根据已经存在的节点自动加1,哪怕有相同名字的节点也不会抛出异常
* ,因为他会在设置的节点名后加数目后缀)
*/
String path = "/zhtest";
zookper.create(path, path.getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
log("创建节点");
/*
* getData 为true会回调Watcher
*/
log("获得节点数据" + new String(zookper.getData(path, true, null)));
/*
* 最后一个参数是预期的匹配版本,为-1就是全匹配
*/
zookper.setData(path, (path + "new").getBytes(), -1);
log("设置节点");
String path1 = "/zhtest1";
zookper.create(path + path1, path1.getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
/*
* 该节点还有子节点会抛出异常
*/
zookper.delete(path + path1, -1);
log("删除子节点");
zookper.delete(path, -1);
log("删除节点");
}
/**
* 集群管理时找到leader
*
* @throws InterruptedException
* @throws KeeperException
* @throws UnknownHostException
*/
public void findLeader() throws UnknownHostException, KeeperException,
InterruptedException {
String leaderPath = "/leader";
String localIp = InetAddress.getLocalHost().toString();
// zookper.create(leaderPath, localIp.getBytes(), Ids.OPEN_ACL_UNSAFE,
// CreateMode.PERSISTENT);
byte[] leader = null;
try {
leader = zookper.getData(leaderPath, true, null);// 看是否有leader
} catch (Exception e) {
e.printStackTrace();
}
log("收到数据" + new String(leader));
String myLeader = null;
if (leader == null) {// 使自己成为leader
myLeader = zookper.create(leaderPath, localIp.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);// 设置为临时的
}
if (myLeader != null) {
log("我是leader");
} else {
log("我不是leader,要等待");
}
}
/**
* 模拟同步锁
*
* @throws InterruptedException
* @throws KeeperException
*/
public void getLock() throws KeeperException, InterruptedException {
String root = "/root";
String myNode = "/myNode";
String realMyNode = zookper.create(root + myNode, myNode.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);// 创建我的节点
List<String> childrenList = zookper.getChildren(root, false);
String[] children = childrenList
.toArray(new String[childrenList.size()]);// 所有子节点
Arrays.sort(children);
log(children[0]);
log(realMyNode);
if (realMyNode.equals(root + "/" + children[0])) {
log("我可以获得锁了");
} else {
log("等吧");
waitForLocak(root + "/" + children[0]);
}
}
private void waitForLocak(String lockNode) throws KeeperException,
InterruptedException {
Stat stat = zookper.exists(lockNode, true);// 在watcher中检测该节点的delete,set,create变化
if (stat != null) {
log("等待watcher的变化");
} else {
log("继续getLock()");
}
}
/**
* 同步队列
*
* @throws InterruptedException
* @throws KeeperException
*/
public void addQueue() throws KeeperException, InterruptedException {
String root = "/root";
int size = 1;// 队列人数
String syncName = "/syncStart";
if (zookper.exists(root + syncName, true) != null) {
log("已经存在" + syncName);
return;
}
String queueNumber = "/queueNumber";
zookper.create(root + queueNumber, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
List<String> list = zookper.getChildren(root, false);// 所有子节点
if (list.size() < size) {
log("人不够,等人进队列吧");// 等待watcher通知
} else {
zookper.create(root + syncName, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
log("人够了");
}
}
/**
* 生产者
*/
private String pc_QueueNode = "/root";
private String pc_QueueMember = "/queueMem";
public void producer(int i) throws KeeperException, InterruptedException {
ByteBuffer buffer = ByteBuffer.allocate(4);// 该类可以用来int,short等类型的数据和byte[]的转换
buffer.putInt(i);
zookper.create(pc_QueueNode + pc_QueueMember, buffer.array(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
log("加入队列了");
}
/**
* 消费者,按FIFO让队列所有生产的全部消费掉
*
* @throws InterruptedException
* @throws KeeperException
*/
public void consumer() throws KeeperException, InterruptedException {
List<String> list = zookper.getChildren(pc_QueueNode, false);
if (list.size() == 0) {
log("队列没人");
return;
}
String[] members = list.toArray(new String[list.size()]);
Arrays.sort(members);
for (String temp : members) {
ByteBuffer buffer = ByteBuffer.wrap(zookper.getData(pc_QueueNode
+ "/" + temp, false, null));
log("数据" + buffer.getInt());
zookper.delete(pc_QueueNode + "/" + temp, -1);
log("移除" + temp);
}
}
public void close() throws InterruptedException {
zookper.close();
log("关闭会话");
}
private void log(String log) {
System.out.println(log);
}
public static void main(String[] args) {
ZKTest zk = null;
try {
zk = new ZKTest();
zk.producer(0);
zk.producer(1);
zk.consumer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (zk != null) {
try {
zk.close();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Zookeeper学习1
最新推荐文章于 2024-03-01 23:55:22 发布