Java 操作zk

一、節點操作

4 種
持久和臨時
無序和有序

1.1持久化節點

public static void createPersistent() {
		if(!zkClient.exists("/java")) {
			String create = zkClient.create("/java", "java", CreateMode.PERSISTENT);
			System.out.println(create);
		}
		if(zkClient.exists("/java/io/inputstream/fileInputstream")) {
//			NoNode , 這個低估創建是自己實現的算法
			zkClient.createPersistent("/java/io/inputstream/fileInputstream", true); // 這個使用最多,它可以遞歸創建節點,zookeeper 原生不支持遞歸創建
		}
	}
	/**
	 * 創建一個持久的順序節點
	 */
	public static void createPerSeq() {
		// zk 不支持創建同名的節點
//		/java0000000004 /java0000000005 /java0000000006
//		String create = zkClient.create("/java", "java", CreateMode.PERSISTENT_SEQUENTIAL);
		String create = zkClient.createPersistentSequential("/java", "java"); // 快捷創建節點
		System.out.println(create);
	}

1.2創建臨時節點

若創建它的客戶端斷開連接後(和zkServer 斷開),則節點會自動刪除
在這裏插入圖片描述

/**
	 * 臨時節點,若創建它的客戶端斷開連接,則自動死掉
	 * 使用多一點
	 */
	public static void createEm() {
		zkClient.createEphemeral("/test");
		try {
			System.out.println("掛起jvm,線程在此一致等待");
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
//		zkClient.close();
	}
	
	// 創建一個臨時的順序節點 使用少
	public static void createEmSeq() {
		
		zkClient.createEphemeralSequential("/test1", "test");
	}

1.3訂閱子節點的改變(重要)

在這裏插入圖片描述

/**
	 * 訂閱節點的改變(重要)
	 */
	public static void subScribe() {
		zkClient.subscribeChildChanges("/com.sxt.AddService", new IZkChildListener() {
			
			/**
			 * 若該父節點的字節有變化,則會執行該方法
			 */
			@Override
			public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
				System.out.println(parentPath+",下的字節點有變化");
				System.out.println("當前最新的子節點爲"+currentChilds);
			}
		});
		System.out.println("開始監聽");
		try {
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

1.4其他的訂閱操作

public static void otherSub() {
//		zkClient.subscribeStateChanges(new IZkStateListener() {
//
//			@Override
//			public void handleStateChanged(KeeperState state) throws Exception {
//            System.out.println("當前狀態爲"+state);
//			}
//
//			@Override
//			public void handleSessionEstablishmentError(Throwable error) throws Exception {
//              System.out.println("寫數據的異常"+error); // 寫數據和時有異常會監聽到
//			}
//
//			@Override
//			public void handleNewSession() throws Exception {
//                System.out.println("新連接"); // 觸發條件是在一個客戶端裏面
//			}
//		});// 訂閱服務器的狀態改變(zkServer狀態的改變,服務器死機了,啓動)
		zkClient.subscribeDataChanges("/java", new IZkDataListener() { // 該監聽針對的是自己(客戶端)內部數據改變
			
			@Override
			public void handleDataDeleted(String dataPath) throws Exception {
				System.out.println(dataPath);
			}
			
			@Override
			public void handleDataChange(String dataPath, Object data) throws Exception {
				System.out.println(dataPath+":::"+data);
			}
		}); // 訂閱節點數據改變的通知
         System.out.println("開始監聽");
		try {
			System.in.read();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

1.5修改節點的數據

/**
	 * 給節點寫數據
	 */
	public static void changeData() {
		zkClient.writeData("/java", "23456");
	}

二、註冊中心

2.1 服務提供者啓動->註冊自己

在這裏插入圖片描述

2.2 服務消費者調用->獲取服務列表

在這裏插入圖片描述

2.3 性能問題

在這裏插入圖片描述
服務消費者每次調用時,都有從zk 上獲取一次數據

在高併發調用,每次去獲取遠程的服務列表,是個性能問題
若每次拉取服務要2 s -0s
遠程需要1 s
=3s->1s

2.4 緩存的思想


在這裏插入圖片描述
查詢數據:管理員的菜單

2.4 緩存的髒讀

緩存裏面的時間和數據源裏面的數據不一致導致
Eg: 現在有個服務掛了,zk 上會自動刪除它,但是緩存列表裏面還有它

若:zk 上節點有變化,能修改我的緩存(訂閱的功能)

/**
	 * 1 第一次從zk 上面拉取 ?
	 * 2 拉取之後保存起來
	 * 3 以後的獲取數據都從緩存裏面找 
	 * 
	 * @param serverName
	 * @return
	 */
	public static List<String>fetchServerListCache(String serverName){
		if(serverList.containsKey(serverName)) { // 代表之前獲取過該服務的列表
			System.out.println("從緩存裏面獲取");
			List<String> list = serverList.get(serverName);
			return list;
		}
		List<String> fetchServerList = fetchServerList(serverName); //不包含,說明之前沒有拉取過,我先拉取到,保存起來
		serverList.put(serverName, fetchServerList);
		// 拉取成功後,我開始關注這個節點,若該節點有變化,我修改緩存裏面的數據
		zkClient.subscribeChildChanges("/"+serverName, new IZkChildListener() {
			
			@Override
			public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
				System.out.println("有服務死機或上線,需要更新服務的列表");
				System.out.println("緩存裏面的服務列表爲"+serverList.get(serverName));
				System.out.println("最新的爲"+currentChilds);
				System.out.println("開始更新");
				serverList.put(serverName, currentChilds);
				System.out.println("修改成功");
				
				
			}
		});
		return fetchServerList;
	}

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