第三章 创建Zookeeper会话【下】

接上节内容:

1、Getting MasterShip(获取主人身份)

创建一个 /master 需要做两件事情,第一:初始化节点数据,第二:需要ACL(Access control list)访问控制表

ACL是一个常量ZooDefs.Ids.OPEN_ACL_UNSAFE(这表明不是安全的,一般用于安全的环境下)

随机生成节点数据:String serverId = Integer.toHexString(random.nextInt());

接口:

void runForMaster(){
  zk.create("/master",
   serverId.getBytes(),
   OPEN_ACL_UNSAFE,
   CreateMode.EPHEMERAL);
}
注释:

  • 第一个参数是要创建的节点为master,如果存在将会创建失败
  • 第二个参数表示存储节点的数据是字节数组
  • 第三个参数使用ACL
  • 第四个参数表示创建一个瞬时节点

创建节点会抛出两个异常:KeeperException(ConnectionLossException是它子类) 和InterruptedException

首先创建一个节点,然后获取master是不是我刚才创建master节点。(启动Zookeeper服务)

package learn;

import java.io.IOException;
import java.util.Random;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.ConnectionLossException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class Master implements Watcher{

	ZooKeeper zk;
	String hostPort;
	private Random random = new Random();
	String serverId = Integer.toHexString(random .nextInt());
	/**
	 * 判断当前领导是否是我,不是返回false,是返回True
	 * 
	 * @return
	 */
	boolean checkMaster(){
		while(true){
			try{
				Stat stat = new Stat();
				byte data[] = zk.getData("/master", false, stat);
				isLeader = new String (data).equals(serverId);
				return true;
			} catch (NoNodeException e){
				return false;
			}catch (ConnectionLossException e){
				
			} catch (KeeperException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建节点失败表示已经有领导者,如果成功,去检查当前领导是否为刚才创建的领导者
	 * @throws InterruptedException
	 */
	void runForMaster() throws InterruptedException{
		while(true){
			try{
				zk.create("/master", serverId.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
				isLeader = true;
				break;
			} catch (NodeExistsException e) {
				isLeader = false;
				break;
			} catch(ConnectionLossException e){
				
			} catch (KeeperException e) {
				e.printStackTrace();
			}
			if (checkMaster()) break;
			
		}
	}
	
	
	static boolean isLeader = false;
	Master(String hostPort){
		this.hostPort = hostPort;
	}
	void startZK() throws IOException{
		zk = new ZooKeeper(hostPort, 15000, this);
	}
	public void process(WatchedEvent e) {

		System.out.println(e);
	}
	
	void stopZK() throws Exception{ //关闭zk
		zk.close();
	}
	
	public static void main(String[] args) throws Exception {
		Master m = new Master(args[0]);
		m.startZK();
		m.runForMaster();
		if(isLeader){
			System.out.println("我是领导者");
			Thread.sleep(60000);
		}else {
			System.out.println("已经有领导者");
		}
		Thread.sleep(60000);
		m.stopZK();
	}

}

2、通过异步获取主人身份

接口与同步类似,只是增加两个参数

void create(String path,
byte[] data,
List<ACL> acl,
CreateMode createMode,
AsyncCallback.StringCallback cb,
Object ctx)
一个是回调函数:类似js的ajax,回调函数

一个上下文对象:打包的数据(包括异常信息)

需要实现如下回调接口

void processResult(int rc, String path, Object ctx, String name)
rc : 返回码,例如OK

path:创建节点路径

ctx : 打包上下文对象

name : 创建的节点的名称

一般创建成功path和name相等,但CreateMode.SEQUENTIAL除外。

package learn;

import java.io.IOException;
import java.util.Random;

import org.apache.zookeeper.AsyncCallback.StringCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.KeeperException.ConnectionLossException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class Master implements Watcher{

	static ZooKeeper zk;
	String hostPort;
	private static Random random = new Random();
	static String serverId = Integer.toHexString(random .nextInt());
	/**
	 * 判断当前领导是否是我,不是返回false,是返回True
	 * 
	 * @return
	 */
	static boolean checkMaster(){
		while(true){
			try{
				Stat stat = new Stat();
				byte data[] = zk.getData("/master", false, stat);
				isLeader = new String (data).equals(serverId);
				return true;
			} catch (NoNodeException e){
				return false;
			}catch (ConnectionLossException e){
				
			} catch (KeeperException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建节点失败表示已经有领导者,如果成功,去检查当前领导是否为刚才创建的领导者
	 * @throws InterruptedException
	 */
	void runForMaster() throws InterruptedException{
		zk.create("/master", serverId.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,
				masterCreateCallback, null);
	}
	
	static boolean isLeader = false;
	//回调函数
	static StringCallback masterCreateCallback = new StringCallback(){
		public void processResult(int rc, String path, Object ctx, String name) {
			switch (Code.get(rc)) {
			case CONNECTIONLOSS:
				checkMaster();
				return;
			case OK:
				isLeader = true;
				break;
			default:
				isLeader=false;
				break;
			}
			System.out.println("我" + (isLeader?"是":"不是") +"领导");
			
		}
		
	};
	Master(String hostPort){
		this.hostPort = hostPort;
	}
	void startZK() throws IOException{
		zk = new ZooKeeper(hostPort, 15000, this);
	}
	public void process(WatchedEvent e) {

		System.out.println(e);
	}
	
	void stopZK() throws Exception{ //关闭zk
		zk.close();
	}
	
	public static void main(String[] args) throws Exception {
		Master m = new Master(args[0]);
		m.startZK();
		m.runForMaster();
		if(isLeader){
			System.out.println("我是领导者");
			Thread.sleep(60000);
		}else {
			System.out.println("已经有领导者");
		}
		Thread.sleep(60000);
		m.stopZK();
	}

}

通过重写DataCallback回调函数

	static DataCallback masterCheckCallback = new DataCallback(){

		public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
			switch(Code.get(rc)){
			case CONNECTIONLOSS:
				checkMaster();
				return;
			case NONODE:
				try {
					runForMaster();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				return;
			default:
				break;
			}
		}
		
	};
       void checkMaster() {
     zk.getData("/master", false, masterCheckCallback, null);
}


3、设置元数据

/tasks, /assign, 和/workers等根节点。通过回调函数创建节点

package learn;

import java.io.IOException;
import java.util.Random;

import org.apache.zookeeper.AsyncCallback.StringCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
public class Master implements Watcher{

	static ZooKeeper zk;
	String hostPort;
	private static Random random = new Random();
	static String serverId = Integer.toHexString(random .nextInt());
	
	Master(String hostPort){
		this.hostPort = hostPort;
	}
	void startZK() throws IOException{
		zk = new ZooKeeper(hostPort, 15000, this);
	}
	public void boostrap(){
		createParent("/workers", new byte[0]);
		createParent("/assign", new byte[0]);
		createParent("/tasks", new byte[0]);
		createParent("/status", new byte[0]);
	}
	private void createParent(String path, byte[] data) {
	
		zk.create(path, data, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, 
				createParentCallback, data);
	}
	StringCallback createParentCallback = new StringCallback() {
		public void processResult(int rc, String path, Object ctx, String name) {
			switch (Code.get(rc)) {
			case CONNECTIONLOSS:
				createParent(path,(byte[]) ctx);
				break;
			case OK:
				System.out.println("父级节点创建成功");
				break;
			case NODEEXISTS:
				System.out.println("父级节点已经存在:" +path);
				break;
			default:
				System.out.println("某个地方出现异常:"+ KeeperException.create(Code.get(rc), path));
				break;
			}
			
		}
	};
	public void process(WatchedEvent e) {

		System.out.println(e);
	}
	
	void stopZK() throws Exception{ //关闭zk
		zk.close();
	}
	
	public static void main(String[] args) throws Exception {
		Master m = new Master(args[0]);
		m.startZK();
		m.boostrap();
		Thread.sleep(60000);
		m.stopZK();
	}

}

4、注册工作者

步骤1:连接服务器

步骤2:创建节点

步骤3:回调函数处理

package learn;

import java.io.IOException;
import java.util.Random;

import org.apache.zookeeper.AsyncCallback.DataCallback;
import org.apache.zookeeper.AsyncCallback.StringCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.KeeperException.ConnectionLossException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class Master implements Watcher{

	static ZooKeeper zk;
	String hostPort;
	private static Random random = new Random();
	static String serverId = Integer.toHexString(random .nextInt());
	
	Master(String hostPort){
		this.hostPort = hostPort;
	}
	void startZK() throws IOException{
		zk = new ZooKeeper(hostPort, 15000, this);
	}
	void register(){
		zk.create("/workers/worker-" +serverId, "Idle".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,
				createWorkerCallback, null);
	}
	
	StringCallback createWorkerCallback = new StringCallback() {
		public void processResult(int rc, String path, Object ctx, String name) {
			switch (Code.get(rc)) {
			case CONNECTIONLOSS:  //表示断开需要重新创建
				register();
				break;
			case OK:
				System.out.println("Worker节点创建成功:" +serverId);
				break;
			case NODEEXISTS:
				System.out.println("Worker节点已经存在:" +serverId);
				break;
			default:
				System.out.println("某个地方出现异常:"+ KeeperException.create(Code.get(rc), path));
				break;
			}
			
		}
	};
	public void process(WatchedEvent e) {

		System.out.println(e);
	}
	
	void stopZK() throws Exception{ //关闭zk
		zk.close();
	}
	
	public static void main(String[] args) throws Exception {
		Master m = new Master(args[0]);
		m.startZK();
		m.register();
		Thread.sleep(60000);
		m.stopZK();
	}

}

更新工作者状态

5、队列任务

为工作者分配任务

package learn;

import java.io.IOException;
import java.util.Random;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException.ConnectionLossException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
public class Master implements Watcher{

	static ZooKeeper zk;
	String hostPort;
	private static Random random = new Random();
	static String serverId = Integer.toHexString(random .nextInt());
	
	Master(String hostPort){
		this.hostPort = hostPort;
	}
	void startZK() throws IOException{
		zk = new ZooKeeper(hostPort, 15000, this);
	}
	String queueCommand(String command) throws Exception {
		while(true){
			try{
				String name = zk.create("/tasks/task-", command.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
				return name;
			}catch (NodeExistsException e){
				throw new Exception(command +"已经存在运行task任务");
			} catch (ConnectionLossException e){
				
			}
		}
	}
	
	public void process(WatchedEvent e) {

		System.out.println(e);
	}
	
	void stopZK() throws Exception{ //关闭zk
		zk.close();
	}
	
	public static void main(String[] args) throws Exception {
		Master m = new Master(args[0]);
		m.startZK();
		String name = m.queueCommand("11");
		System.out.println("创建task节点: " + name);
		Thread.sleep(60000);
		m.stopZK();
	}

}



6、创建简单一个管理客户端  , 打印当前服务器节点master,worker,task数据

package learn;

import java.util.Date;

import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class AdminClient implements Watcher{
	ZooKeeper zk;
	String hostPort;
	AdminClient(String hostPort) {
		this.hostPort = hostPort;
	}
	
	void listState() throws Exception {
		try {
			Stat stat = new Stat();
			byte masterData[] = zk.getData("/masters", false, stat);
			Date startDate = new Date(stat.getCtime());
			System.out.println("Master: " + new String(masterData) + "时间为:" + startDate);
		}catch (NoNodeException e) {
			System.out.println("没有master");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("工作者:");
		for(String w:zk.getChildren("/workers", false)){
			byte data[] = zk.getData("/workers" + w, false, null);
			String state = new String(data);
			System.out.println("\t" +w + ": " + state);
		}
		System.out.println("任务:");
		for(String t:zk.getChildren("/assign", false)){
			System.out.println("\t" + t);
		}
	}
	void start() throws Exception {
		zk = new ZooKeeper(hostPort, 15000, this);
	}
	public void process(WatchedEvent e) {
		System.out.println(e);
		
	}
	public static void main(String[] args) throws Exception {
		AdminClient c = new AdminClient("127.0.0.1:2181");
		c.start();
		c.listState();
	}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值