1. 程式人生 > >Zookeeper學習筆記十之 非同步實現主節點選舉

Zookeeper學習筆記十之 非同步實現主節點選舉

非同步實現主節點選舉 

    Zookeeper中,所有同步呼叫方法都有對應的非同步呼叫方法,通過非同步呼叫,我們可以在單執行緒中同時進行多個呼叫,接下來實現一個非同步實現主節點選舉的例子

       Zookeeper.create方法的非同步呼叫版本

       void create(String path, byte data[], List acl, CreateMode createMode, AsyncCallback.StringCallback cb,Object ctx) ,相較於同步呼叫,多了StringCallback ,和Object兩個引數。StringCallback 提供回撥方法的物件,Object使用者指定上下文資訊

程式碼示例

package com.my.service;

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.Code;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class MyZookeeper {

	private ZooKeeper zooKeeper;
	private String hostPort;
	private Random random = new Random(47);
	private String serverId = Integer.toString(random.nextInt());
	boolean isMaster = false;

	public MyZookeeper(String hostPort) {
		this.hostPort = hostPort;
	}

	// 建立一個zk連線監視點,列印斷開連線日誌資訊
	Watcher watcher = new Watcher() {

		public void process(WatchedEvent event) {
			// 如果監控到與服務端連線斷開,列印日誌
			if (KeeperState.Disconnected.equals(event.getState())) {
				System.out.println("Zookeeper Disconnected!客戶端與ZooKeeper伺服器連線斷開!");
			}

		}

	};

	// 連線到zk服務端
	public void startZk() throws IOException {
		zooKeeper = new ZooKeeper(hostPort, 15000, watcher);
	}

	public void stopZk() throws InterruptedException {
		zooKeeper.close();
	}

	// 實現一個回撥的介面,並建立例項
	StringCallback masterCallback = new StringCallback() {

		public void processResult(int rc, String path, Object ctx, String name) {
			switch (Code.get(rc)) {// rc返回呼叫的結構,返回OK或與KeeperException異常對應的編碼值
			case CONNECTIONLOSS:
				checkMasterSync();
				return;
			case OK:
				//建立成功,成為主節點
				isMaster = true;
				break;
			default:
				isMaster = false;
			}
			System.out.println("I am" + (isMaster ? "" : "not") + " the master");
		}
	};
	// 實現一個檢查資料的回撥介面,並建立例項
	DataCallback masterCheckCallBack = new DataCallback() {

		public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
			switch (Code.get(rc)) {
			case CONNECTIONLOSS:
				checkMasterSync();
				return;
			case NONODE:
				//主節點不存在,進行非同步主節點建立
				runForMasterSync();
				return;

			}
		}

	};

	public void checkMasterSync() {
		zooKeeper.getData("/master", false, masterCheckCallBack, null);
	}

	public void runForMasterSync() {
		zooKeeper.create("/master", serverId.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,
				masterCallback, null);
	}

	public static void main(String[] args) throws IOException, InterruptedException {

		MyZookeeper myZookeeper = new MyZookeeper("127.0.0.1:2181");
		myZookeeper.startZk();
		myZookeeper.runForMasterSync();
		//執行緒休眠一段時間,觀看非同步建立效果
		Thread.sleep(5000);
		if (myZookeeper.isMaster) {
			System.out.println("我是主節點");
			Thread.sleep(60000);
		} else {
			System.out.println("其他節點已經成為了主節點");
		}
	}
}