0 課程地址
https://coding.imooc.com/lesson/201.html#mid=12737
1 重點關注
1.1 本節內容
curator自帶節點監聽多次,監聽子節點(可以針對增刪改不同類型的節點修改類型判斷)
1.2 關鍵代碼
// 爲子節點添加watcher // PathChildrenCache: 監聽數據節點的增刪改,會觸發事件 String childNodePathCache = nodePath; // cacheData: 設置緩存節點的數據狀態 final PathChildrenCache childrenCache = new PathChildrenCache(cto.client, childNodePathCache, true); /** * StartMode: 初始化方式 * POST_INITIALIZED_EVENT:異步初始化,初始化之後會觸發事件,這個經常使用 * NORMAL:異步初始化 這個不常用,更多的異步處理需要觸發事件 * BUILD_INITIAL_CACHE:同步初始化,這個用的較少,同步無法觸發事件 */ childrenCache.start(StartMode.POST_INITIALIZED_EVENT); List<ChildData> childDataList = childrenCache.getCurrentData(); System.out.println("當前數據節點的子節點數據列表:"); for (ChildData cd : childDataList) { String childData = new String(cd.getData()); System.out.println(childData); } // 根據event.getType判斷節點變化類型 childrenCache.getListenable().addListener(new PathChildrenCacheListener() { public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { if(event.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)){ System.out.println("子節點初始化ok..."); } // 這裏的數據路徑,通常可以從配置平臺和環境變量獲取,匹配到對應節點只能對特定文件生效 else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){ String path = event.getData().getPath(); if (path.equals(ADD_PATH)) { System.out.println("添加子節點:" + event.getData().getPath()); System.out.println("子節點數據:" + new String(event.getData().getData())); } else if (path.equals("/super/imooc/e")) { System.out.println("添加不正確..."); } }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){ System.out.println("刪除子節點:" + event.getData().getPath()); }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){ System.out.println("修改子節點路徑:" + event.getData().getPath()); System.out.println("修改子節點數據:" + new String(event.getData().getData())); } } }); Thread.sleep(1000000); cto.closeZKClient(); boolean isZkCuratorStarted2 = cto.client.isStarted(); System.out.println("當前客戶的狀態:" + (isZkCuratorStarted2 ? "連接中" : "已關閉")); } public final static String ADD_PATH = "/super/imooc/d";
2 課程內容
3 Coding
3.1 Curator使用監聽(可判斷節點變更類型)
- 啓動服務端
進入到
cd /usr/local/zookeeper/bin
重啓zookeeper服務端
./zkServer.sh restart
- 主類
package com.imooc.curator; import java.util.List; import org.apache.curator.RetryPolicy; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.recipes.cache.ChildData; import org.apache.curator.framework.recipes.cache.NodeCache; import org.apache.curator.framework.recipes.cache.NodeCacheListener; import org.apache.curator.framework.recipes.cache.PathChildrenCache; import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode; import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; import org.apache.curator.retry.RetryNTimes; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.data.Stat; public class CuratorOperator { public CuratorFramework client = null; public static final String zkServerPath = "172.26.139.4:2181"; /** * 實例化zk客戶端 */ public CuratorOperator() { /** * 同步創建zk示例,原生api是異步的 * * curator鏈接zookeeper的策略:ExponentialBackoffRetry * baseSleepTimeMs:初始sleep的時間 * maxRetries:最大重試次數 * maxSleepMs:最大重試時間 */ // RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5); /** * curator鏈接zookeeper的策略:RetryNTimes * n:重試的次數 * sleepMsBetweenRetries:每次重試間隔的時間 */ RetryPolicy retryPolicy = new RetryNTimes(3, 5000); /** * curator鏈接zookeeper的策略:RetryOneTime * sleepMsBetweenRetry:每次重試間隔的時間 */ // RetryPolicy retryPolicy2 = new RetryOneTime(3000); /** * 永遠重試,不推薦使用 */ // RetryPolicy retryPolicy3 = new RetryForever(retryIntervalMs) /** * curator鏈接zookeeper的策略:RetryUntilElapsed * maxElapsedTimeMs:最大重試時間 * sleepMsBetweenRetries:每次重試間隔 * 重試時間超過maxElapsedTimeMs後,就不再重試 */ // RetryPolicy retryPolicy4 = new RetryUntilElapsed(2000, 3000); client = CuratorFrameworkFactory.builder() .connectString(zkServerPath) .sessionTimeoutMs(10000).retryPolicy(retryPolicy) .namespace("workspace").build(); client.start(); } /** * * @Description: 關閉zk客戶端連接 */ public void closeZKClient() { if (client != null) { this.client.close(); } } public static void main(String[] args) throws Exception { // 實例化 CuratorOperator cto = new CuratorOperator(); boolean isZkCuratorStarted = cto.client.isStarted(); System.out.println("當前客戶的狀態:" + (isZkCuratorStarted ? "連接中" : "已關閉")); // 創建節點 String nodePath = "/super/imooc"; // byte[] data = "superme".getBytes(); // cto.client.create().creatingParentsIfNeeded() // .withMode(CreateMode.PERSISTENT) // .withACL(Ids.OPEN_ACL_UNSAFE) // .forPath(nodePath, data); // 更新節點數據 // byte[] newData = "batman".getBytes(); // cto.client.setData().withVersion(0).forPath(nodePath, newData); // 刪除節點 // cto.client.delete() // .guaranteed() // 如果刪除失敗,那麼在後端還是繼續會刪除,直到成功 // .deletingChildrenIfNeeded() // 如果有子節點,就刪除 // .withVersion(0) // .forPath(nodePath); // 讀取節點數據 // Stat stat = new Stat(); // byte[] data = cto.client.getData().storingStatIn(stat).forPath(nodePath); // System.out.println("節點" + nodePath + "的數據爲: " + new String(data)); // System.out.println("該節點的版本號爲: " + stat.getVersion()); // 查詢子節點 // List<String> childNodes = cto.client.getChildren() // .forPath(nodePath); // System.out.println("開始打印子節點:"); // for (String s : childNodes) { // System.out.println(s); // } // 判斷節點是否存在,如果不存在則爲空 // Stat statExist = cto.client.checkExists().forPath(nodePath + "/abc"); // System.out.println(statExist); // watcher 事件 當使用usingWatcher的時候,監聽只會觸發一次,監聽完畢後就銷燬 // cto.client.getData().usingWatcher(new MyCuratorWatcher()).forPath(nodePath); // cto.client.getData().usingWatcher(new MyWatcher()).forPath(nodePath); // 爲節點添加watcher // NodeCache: 監聽數據節點的變更,會觸發事件 // final NodeCache nodeCache = new NodeCache(cto.client, nodePath); // // buildInitial : 初始化的時候獲取node的值並且緩存 // nodeCache.start(true); // if (nodeCache.getCurrentData() != null) { // System.out.println("節點初始化數據爲:" + new String(nodeCache.getCurrentData().getData())); // } else { // System.out.println("節點初始化數據爲空..."); // } // nodeCache.getListenable().addListener(new NodeCacheListener() { // public void nodeChanged() throws Exception { // if (nodeCache.getCurrentData() == null) { // System.out.println("空"); // return; // } // String data = new String(nodeCache.getCurrentData().getData()); // System.out.println("節點路徑:" + nodeCache.getCurrentData().getPath() + "數據:" + data); // } // }); // 爲子節點添加watcher // PathChildrenCache: 監聽數據節點的增刪改,會觸發事件 String childNodePathCache = nodePath; // cacheData: 設置緩存節點的數據狀態 final PathChildrenCache childrenCache = new PathChildrenCache(cto.client, childNodePathCache, true); /** * StartMode: 初始化方式 * POST_INITIALIZED_EVENT:異步初始化,初始化之後會觸發事件 * NORMAL:異步初始化 * BUILD_INITIAL_CACHE:同步初始化 */ childrenCache.start(StartMode.POST_INITIALIZED_EVENT); List<ChildData> childDataList = childrenCache.getCurrentData(); System.out.println("當前數據節點的子節點數據列表:"); for (ChildData cd : childDataList) { String childData = new String(cd.getData()); System.out.println(childData); } childrenCache.getListenable().addListener(new PathChildrenCacheListener() { public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { if(event.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)){ System.out.println("子節點初始化ok..."); } else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){ String path = event.getData().getPath(); if (path.equals(ADD_PATH)) { System.out.println("添加子節點:" + event.getData().getPath()); System.out.println("子節點數據:" + new String(event.getData().getData())); } else if (path.equals("/super/imooc/e")) { System.out.println("添加不正確..."); } }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){ System.out.println("刪除子節點:" + event.getData().getPath()); }else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){ System.out.println("修改子節點路徑:" + event.getData().getPath()); System.out.println("修改子節點數據:" + new String(event.getData().getData())); } } }); Thread.sleep(1000000); cto.closeZKClient(); boolean isZkCuratorStarted2 = cto.client.isStarted(); System.out.println("當前客戶的狀態:" + (isZkCuratorStarted2 ? "連接中" : "已關閉")); } public final static String ADD_PATH = "/super/imooc/d"; }
- linux客戶端修改節點(修改多次)
--啓動linux客戶端 zkCli.sh --初始化節點 [zk: localhost:2181(CONNECTED) 2] create /workspace/super/imooc/d d Created /workspace/super/imooc/d [zk: localhost:2181(CONNECTED) 3] create /workspace/super/imooc/a a Created /workspace/super/imooc/a [zk: localhost:2181(CONNECTED) 4] create /workspace/super/imooc/b b Created /workspace/super/imooc/b [zk: localhost:2181(CONNECTED) 5] create /workspace/super/imooc/c c Created /workspace/super/imooc/c [zk: localhost:2181(CONNECTED) 6] ls /workspace/super/imooc [a, b, c, d] --啓動sts客戶端後,進行修改節點 [zk: localhost:2181(CONNECTED) 7] set /workspace/super/imooc/d ddd cZxid = 0x101 ctime = Wed Apr 10 06:32:42 CST 2024 mZxid = 0x106 mtime = Wed Apr 10 06:34:50 CST 2024 pZxid = 0x101 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0 [zk: localhost:2181(CONNECTED) 8] set /workspace/super/imooc/a aaa cZxid = 0x102 ctime = Wed Apr 10 06:32:47 CST 2024 mZxid = 0x107 mtime = Wed Apr 10 06:35:04 CST 2024 pZxid = 0x102 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0 --啓動sts客戶端後,進行刪除節點 [zk: localhost:2181(CONNECTED) 9] delete /workspace/super/imooc/d --啓動sts客戶端後,進行創建節點 [zk: localhost:2181(CONNECTED) 10] create /workspace/super/imooc/d [zk: localhost:2181(CONNECTED) 11] create /workspace/super/imooc/d d2 Created /workspace/super/imooc/d [zk: localhost:2181(CONNECTED) 12] create /workspace/super/imooc/a a2 Node already exists: /workspace/super/imooc/a --啓動sts客戶端後,驗證不同目錄操作打印 [zk: localhost:2181(CONNECTED) 13] create /workspace/super/imooc/e e2 Created /workspace/super/imooc/e
- 打印日誌(監聽多次)
2024-04-10 06:34:34,150 [main] [org.apache.zookeeper.Environment.logEnv(Environment.java:100)] - [INFO] Client environment:os.version=10.0 2024-04-10 06:34:34,151 [main] [org.apache.zookeeper.Environment.logEnv(Environment.java:100)] - [INFO] Client environment:user.name=18612 2024-04-10 06:34:34,152 [main] [org.apache.zookeeper.Environment.logEnv(Environment.java:100)] - [INFO] Client environment:user.home=C:\Users\18612 2024-04-10 06:34:34,153 [main] [org.apache.zookeeper.Environment.logEnv(Environment.java:100)] - [INFO] Client environment:user.dir=D:\project\xin\zk_sts_imooc\imooc-zk-curator-maven 2024-04-10 06:34:34,153 [main] [org.apache.zookeeper.ZooKeeper.<init>(ZooKeeper.java:441)] - [INFO] Initiating client connection, connectString=172.26.139.4:2181 sessionTimeout=10000 watcher=org.apache.curator.ConnectionState@595b007d 2024-04-10 06:34:34,365 [main] [org.apache.curator.framework.imps.CuratorFrameworkImpl.start(CuratorFrameworkImpl.java:326)] - [INFO] Default schema 當前客戶的狀態:連接中 2024-04-10 06:34:34,371 [main-SendThread(172.26.139.4:2181)] [org.apache.zookeeper.ClientCnxn$SendThread.logStartConnect(ClientCnxn.java:1035)] - [INFO] Opening socket connection to server 172.26.139.4/172.26.139.4:2181. Will not attempt to authenticate using SASL (unknown error) 2024-04-10 06:34:34,381 [main-SendThread(172.26.139.4:2181)] [org.apache.zookeeper.ClientCnxn$SendThread.primeConnection(ClientCnxn.java:877)] - [INFO] Socket connection established to 172.26.139.4/172.26.139.4:2181, initiating session 2024-04-10 06:34:34,389 [main-SendThread(172.26.139.4:2181)] [org.apache.zookeeper.ClientCnxn$SendThread.onConnected(ClientCnxn.java:1302)] - [INFO] Session establishment complete on server 172.26.139.4/172.26.139.4:2181, sessionid = 0x1003feb17e7000d, negotiated timeout = 10000 當前數據節點的子節點數據列表: 2024-04-10 06:34:34,397 [main-EventThread] [org.apache.curator.framework.state.ConnectionStateManager.postState(ConnectionStateManager.java:237)] - [INFO] State change: CONNECTED 添加子節點:/super/imooc/d 子節點數據:d 子節點初始化ok... 修改子節點路徑:/super/imooc/d 修改子節點數據:ddd 修改子節點路徑:/super/imooc/a 修改子節點數據:aaa 刪除子節點:/super/imooc/d 添加子節點:/super/imooc/d 子節點數據:d2 添加不正確...