Zookeeper学习1

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();
				}
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值