zookeeper學習之路(五)利用臨時節點,監控服務是否在線

package com ;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class ZKServer implements Watcher{

	public static void main(String[] args) throws Exception {
		 new ZKServer();
	}
	
	private final long delay= 2*1000l;
	private final long period= 5*1000l;
	private final String connectStr ="192.168.8.192:2181,192.168.8.135:2181,192.168.8.136:2181";
	private final int sessionTimeout = 3000;
	private final long zkCreateWaitTime = 30;
	private ZooKeeper zkClient;
	private CountDownLatch cdl= new CountDownLatch(1);
	private final String parentPath="/servers";
	//充當redis
	private Map<String, Object> map = new LinkedHashMap<>(16);
	String treeStr = null;
	
	public ZKServer(){
		createZkClient();
	}

	/**
	 * 添加一個節點
	 * @param hostname
	 */
	private void regist(String hostname){
		String path = null;
		try {
			String node= parentPath+"/server";
			if(zkClient.exists(node, false) !=null){
				System.out.println("node "+node+"  已存在");
				return ;
			}
			path = zkClient.create(node, hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.err.println("node add "+path+" sussess  info "+hostname);
	}

	/**
	 * 定時刷新緩存
	 */
	private void  cacheStatusChecker(){
		Timer rTimer =new Timer();
		rTimer.schedule(task, delay, period);
	}
	
	private TimerTask  task=  new TimerTask() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			reloadCache();
		}
	};
	
	private void reloadCache(){
		if(null == zkClient && !zkClient.getState().isConnected()) 
			return;
		 getChlidren();
	};
	
	private void getChlidren() {
		getChlidren(parentPath);
//		getChlidrenTree(parentPath);
	}
	
	/**
	 * 遞歸獲取節點信息
	 */
	private void getChlidren(String path)  {
		try {
			if(path.equals(parentPath)){
				byte[] data = zkClient.getData(path, false, null);
				map.put(path, new String(data));
			}
			
			List<String> children = zkClient.getChildren(path, true);
			if(children.isEmpty() || children.size()==0){
				return ;
			}
			for (String child : children) {
				String key = path+"/"+child;
				byte[] data = zkClient.getData(key, false, null);
				map.put(key, new String(data));
				getChlidren(key);
			}
		} catch ( Exception e) {
			// TODO Auto-generated catch block
			System.err.println("獲取節點信息異常");
		} 
		 System.err.println("reloadCache : "+map.toString() );
	}
	
	/**
	 * 樹形數據
	 * @param path
	 */
	private void getChlidrenTree(String path)  {
		try {
			if(path.equals(parentPath)){
				JSONObject j = new JSONObject();
				byte[] data = zkClient.getData(path, false, null);
				j.put("path", path);
				j.put("data", new String(data));
				j.put("node", nodeBinning(path));
				treeStr = j.toJSONString();
			}else{
				treeStr = nodeBinning(path);
			}
		} catch ( Exception e) {
			// TODO Auto-generated catch block
			System.err.println("獲取節點信息異常");
		} 
		 System.err.println("reloadCache : " + treeStr);
	}
	
	private String nodeBinning(String path) throws KeeperException, InterruptedException{
		List<String> children = zkClient.getChildren(path, true);
		JSONArray ja = new JSONArray();
		for (String child : children) {
			JSONObject j = new JSONObject();
			String key = path+"/"+child;
			byte[] data = zkClient.getData(key, false, null);
			j.put("path", key);
			j.put("data", new String(data));
			j.put("node", nodeBinning(key));
			ja.add(j);
		}
		return ja.toJSONString();
	}
	
	/**
	 * 創建zk連接
	 * @return
	 */
	private boolean createZkClient(){
		try {
			zkClient = new ZooKeeper(connectStr , sessionTimeout , this);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			System.out.println(" zookeeper 連接異常" +connectStr +"  err : " +e1);
			//e1.printStackTrace();
		}
		
		cdl= new CountDownLatch(1);
		try {
			cdl.await(zkCreateWaitTime, TimeUnit.SECONDS);
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			System.out.println("等待連接時出現異常"+"  err : " +e);
		}
		
		if(zkClient!=null){
			try {
				if(zkClient.exists(parentPath, false) !=null){
					 regist("123") ;
					 cacheStatusChecker();
					return true;
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				System.out.println("zookeeper 客戶端異常  err : " +e);
			} 
		}
		return false;
	}
	
	/**
	 * 監聽回調
	 */
	@Override
	public void process(WatchedEvent event) {
		// TODO Auto-generated method stub
		String path = event.getPath();
		if (event.getState() == KeeperState.Expired){
			 System.out.println("session超時,zookeeper服務器連接失敗");
			 createZkClient();
		}else if((event.getState() == KeeperState.SyncConnected)||
				event.getState() == KeeperState.ConnectedReadOnly){
			 System.out.println("zookeeper已連接成功");
			 cdl.countDown();//連接成功後,主線程開始執行
//			 try {
//				Thread.sleep(10000);
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//				System.out.println("Thread.sleep(10000)  " + e);
//			}
			
			if (event.getType() == EventType.NodeCreated) {
					System.out.println("zookeeper有新節點創建" + event.getPath());
			}
			if (event.getType() == EventType.NodeDataChanged) {
				System.out.println("zookeeper有節點數據變化" + event.getPath());
			}
			if (event.getType() == EventType.NodeDeleted) {
				System.out.println("zookeeper有節點被刪除" + event.getPath());
			}
			if (event.getType() == EventType.NodeChildrenChanged) {
				System.out.println("zookeeper有子節點變化" + event.getPath());
			}
		}else{
			System.out.println("zookeeper 未判斷異常 path "+path+"  event"+event);
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章