0 課程地址
https://coding.imooc.com/lesson/201.html#mid=12747
1 重點關注
1.1 本節內容
curator統一更新N臺節點的配置文件
1.2 關鍵代碼
- curator統一更新N臺配置文件示例
public static CountDownLatch countDown = new CountDownLatch(1); public static void main(String[] args) throws Exception { Client1 cto = new Client1(); System.out.println("client1 啓動成功..."); final PathChildrenCache childrenCache = new PathChildrenCache(cto.client, CONFIG_NODE_PATH, true); childrenCache.start(StartMode.BUILD_INITIAL_CACHE); // 添加監聽事件 childrenCache.getListenable().addListener(new PathChildrenCacheListener() { public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { // 監聽節點變化 if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){ String configNodePath = event.getData().getPath(); if (configNodePath.equals(CONFIG_NODE_PATH + SUB_PATH)) { System.out.println("監聽到配置發生變化,節點路徑爲:" + configNodePath); // 讀取節點數據 String jsonConfig = new String(event.getData().getData()); System.out.println("節點" + CONFIG_NODE_PATH + "的數據爲: " + jsonConfig); // 從json轉換配置 RedisConfig redisConfig = null; if (StringUtils.isNotBlank(jsonConfig)) { redisConfig = JsonUtils.jsonToPojo(jsonConfig, RedisConfig.class); } // 配置不爲空則進行相應操作 if (redisConfig != null) { String type = redisConfig.getType(); String url = redisConfig.getUrl(); String remark = redisConfig.getRemark(); // 判斷事件 if (type.equals("add")) { System.out.println("監聽到新增的配置,準備下載..."); // ... 連接ftp服務器,根據url找到相應的配置 Thread.sleep(500); System.out.println("開始下載新的配置文件,下載路徑爲<" + url + ">"); // ... 下載配置到你指定的目錄 Thread.sleep(1000); System.out.println("下載成功,已經添加到項目中"); // ... 拷貝文件到項目目錄 } else if (type.equals("update")) { System.out.println("監聽到更新的配置,準備下載..."); // ... 連接ftp服務器,根據url找到相應的配置 Thread.sleep(500); System.out.println("開始下載配置文件,下載路徑爲<" + url + ">"); // ... 下載配置到你指定的目錄 Thread.sleep(1000); System.out.println("下載成功..."); System.out.println("刪除項目中原配置文件..."); Thread.sleep(100); // ... 刪除原文件 System.out.println("拷貝配置文件到項目目錄..."); // ... 拷貝文件到項目目錄 } else if (type.equals("delete")) { System.out.println("監聽到需要刪除配置"); System.out.println("刪除項目中原配置文件..."); } // TODO 視情況統一重啓服務 } } } } }); countDown.await();
2 課程內容
3 Coding
3.1 curator新增節點時附帶權限(遞歸給所有子節點權限)
- 啓動服務端
進入到
cd /usr/local/zookeeper/bin
重啓zookeeper服務端
./zkServer.sh restart
- 主類(客戶端1)
package com.imooc.curator.checkConfig; import java.util.List; import java.util.concurrent.CountDownLatch; import org.apache.commons.lang3.StringUtils; 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.PathChildrenCache; import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode; import org.apache.curator.retry.RetryNTimes; import com.imooc.utils.JsonUtils; import com.imooc.utils.RedisConfig; public class Client1 { public CuratorFramework client = null; public static final String zkServerPath = "172.26.139.4:2181"; public Client1() { RetryPolicy retryPolicy = new RetryNTimes(3, 5000); client = CuratorFrameworkFactory.builder() .connectString(zkServerPath) .sessionTimeoutMs(10000).retryPolicy(retryPolicy) .namespace("workspace").build(); client.start(); } public void closeZKClient() { if (client != null) { this.client.close(); } } // public final static String CONFIG_NODE = "/super/imooc/redis-config"; public final static String CONFIG_NODE_PATH = "/super/imooc"; public final static String SUB_PATH = "/redis-config"; public static CountDownLatch countDown = new CountDownLatch(1); public static void main(String[] args) throws Exception { Client1 cto = new Client1(); System.out.println("client1 啓動成功..."); final PathChildrenCache childrenCache = new PathChildrenCache(cto.client, CONFIG_NODE_PATH, true); childrenCache.start(StartMode.BUILD_INITIAL_CACHE); // 添加監聽事件 childrenCache.getListenable().addListener(new PathChildrenCacheListener() { public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { // 監聽節點變化 if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){ String configNodePath = event.getData().getPath(); if (configNodePath.equals(CONFIG_NODE_PATH + SUB_PATH)) { System.out.println("監聽到配置發生變化,節點路徑爲:" + configNodePath); // 讀取節點數據 String jsonConfig = new String(event.getData().getData()); System.out.println("節點" + CONFIG_NODE_PATH + "的數據爲: " + jsonConfig); // 從json轉換配置 RedisConfig redisConfig = null; if (StringUtils.isNotBlank(jsonConfig)) { redisConfig = JsonUtils.jsonToPojo(jsonConfig, RedisConfig.class); } // 配置不爲空則進行相應操作 if (redisConfig != null) { String type = redisConfig.getType(); String url = redisConfig.getUrl(); String remark = redisConfig.getRemark(); // 判斷事件 if (type.equals("add")) { System.out.println("監聽到新增的配置,準備下載..."); // ... 連接ftp服務器,根據url找到相應的配置 Thread.sleep(500); System.out.println("開始下載新的配置文件,下載路徑爲<" + url + ">"); // ... 下載配置到你指定的目錄 Thread.sleep(1000); System.out.println("下載成功,已經添加到項目中"); // ... 拷貝文件到項目目錄 } else if (type.equals("update")) { System.out.println("監聽到更新的配置,準備下載..."); // ... 連接ftp服務器,根據url找到相應的配置 Thread.sleep(500); System.out.println("開始下載配置文件,下載路徑爲<" + url + ">"); // ... 下載配置到你指定的目錄 Thread.sleep(1000); System.out.println("下載成功..."); System.out.println("刪除項目中原配置文件..."); Thread.sleep(100); // ... 刪除原文件 System.out.println("拷貝配置文件到項目目錄..."); // ... 拷貝文件到項目目錄 } else if (type.equals("delete")) { System.out.println("監聽到需要刪除配置"); System.out.println("刪除項目中原配置文件..."); } // TODO 視情況統一重啓服務 } } } } }); countDown.await(); cto.closeZKClient(); } }
- 主類(客戶端2)
package com.imooc.curator.checkConfig; import java.util.List; import java.util.concurrent.CountDownLatch; import org.apache.commons.lang3.StringUtils; 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.PathChildrenCache; import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode; import org.apache.curator.retry.RetryNTimes; import com.imooc.utils.JsonUtils; import com.imooc.utils.RedisConfig; public class Client2 { public CuratorFramework client = null; public static final String zkServerPath = "172.26.139.4:2181"; public Client2() { RetryPolicy retryPolicy = new RetryNTimes(3, 5000); client = CuratorFrameworkFactory.builder() .connectString(zkServerPath) .sessionTimeoutMs(10000).retryPolicy(retryPolicy) .namespace("workspace").build(); client.start(); } public void closeZKClient() { if (client != null) { this.client.close(); } } // public final static String CONFIG_NODE = "/super/imooc/redis-config"; public final static String CONFIG_NODE_PATH = "/super/imooc"; public final static String SUB_PATH = "/redis-config"; public static CountDownLatch countDown = new CountDownLatch(1); public static void main(String[] args) throws Exception { Client2 cto = new Client2(); System.out.println("client2 啓動成功..."); final PathChildrenCache childrenCache = new PathChildrenCache(cto.client, CONFIG_NODE_PATH, true); childrenCache.start(StartMode.BUILD_INITIAL_CACHE); // 添加監聽事件 childrenCache.getListenable().addListener(new PathChildrenCacheListener() { public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { // 監聽節點變化 if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){ String configNodePath = event.getData().getPath(); if (configNodePath.equals(CONFIG_NODE_PATH + SUB_PATH)) { System.out.println("監聽到配置發生變化,節點路徑爲:" + configNodePath); // 讀取節點數據 String jsonConfig = new String(event.getData().getData()); System.out.println("節點" + CONFIG_NODE_PATH + "的數據爲: " + jsonConfig); // 從json轉換配置 RedisConfig redisConfig = null; if (StringUtils.isNotBlank(jsonConfig)) { redisConfig = JsonUtils.jsonToPojo(jsonConfig, RedisConfig.class); } // 配置不爲空則進行相應操作 if (redisConfig != null) { String type = redisConfig.getType(); String url = redisConfig.getUrl(); String remark = redisConfig.getRemark(); // 判斷事件 if (type.equals("add")) { System.out.println("監聽到新增的配置,準備下載..."); // ... 連接ftp服務器,根據url找到相應的配置 Thread.sleep(500); System.out.println("開始下載新的配置文件,下載路徑爲<" + url + ">"); // ... 下載配置到你指定的目錄 Thread.sleep(1000); System.out.println("下載成功,已經添加到項目中"); // ... 拷貝文件到項目目錄 } else if (type.equals("update")) { System.out.println("監聽到更新的配置,準備下載..."); // ... 連接ftp服務器,根據url找到相應的配置 Thread.sleep(500); System.out.println("開始下載配置文件,下載路徑爲<" + url + ">"); // ... 下載配置到你指定的目錄 Thread.sleep(1000); System.out.println("下載成功..."); System.out.println("刪除項目中原配置文件..."); Thread.sleep(100); // ... 刪除原文件 System.out.println("拷貝配置文件到項目目錄..."); // ... 拷貝文件到項目目錄 } else if (type.equals("delete")) { System.out.println("監聽到需要刪除配置"); System.out.println("刪除項目中原配置文件..."); } // TODO 視情況統一重啓服務 } } } } }); countDown.await(); cto.closeZKClient(); } }
- 主類(客戶端3)
package com.imooc.curator.checkConfig; import java.util.List; import java.util.concurrent.CountDownLatch; import org.apache.commons.lang3.StringUtils; 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.PathChildrenCache; import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode; import org.apache.curator.retry.RetryNTimes; import com.imooc.utils.JsonUtils; import com.imooc.utils.RedisConfig; public class Client3 { public CuratorFramework client = null; public static final String zkServerPath = "172.26.139.4:2181"; public Client3() { RetryPolicy retryPolicy = new RetryNTimes(3, 5000); client = CuratorFrameworkFactory.builder() .connectString(zkServerPath) .sessionTimeoutMs(10000).retryPolicy(retryPolicy) .namespace("workspace").build(); client.start(); } public void closeZKClient() { if (client != null) { this.client.close(); } } // public final static String CONFIG_NODE = "/super/imooc/redis-config"; public final static String CONFIG_NODE_PATH = "/super/imooc"; public final static String SUB_PATH = "/redis-config"; public static CountDownLatch countDown = new CountDownLatch(1); public static void main(String[] args) throws Exception { Client3 cto = new Client3(); System.out.println("client3 啓動成功..."); final PathChildrenCache childrenCache = new PathChildrenCache(cto.client, CONFIG_NODE_PATH, true); childrenCache.start(StartMode.BUILD_INITIAL_CACHE); // 添加監聽事件 childrenCache.getListenable().addListener(new PathChildrenCacheListener() { public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { // 監聽節點變化 if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){ String configNodePath = event.getData().getPath(); if (configNodePath.equals(CONFIG_NODE_PATH + SUB_PATH)) { System.out.println("監聽到配置發生變化,節點路徑爲:" + configNodePath); // 讀取節點數據 String jsonConfig = new String(event.getData().getData()); System.out.println("節點" + CONFIG_NODE_PATH + "的數據爲: " + jsonConfig); // 從json轉換配置 RedisConfig redisConfig = null; if (StringUtils.isNotBlank(jsonConfig)) { redisConfig = JsonUtils.jsonToPojo(jsonConfig, RedisConfig.class); } // 配置不爲空則進行相應操作 if (redisConfig != null) { String type = redisConfig.getType(); String url = redisConfig.getUrl(); String remark = redisConfig.getRemark(); // 判斷事件 if (type.equals("add")) { System.out.println("監聽到新增的配置,準備下載..."); // ... 連接ftp服務器,根據url找到相應的配置 Thread.sleep(500); System.out.println("開始下載新的配置文件,下載路徑爲<" + url + ">"); // ... 下載配置到你指定的目錄 Thread.sleep(1000); System.out.println("下載成功,已經添加到項目中"); // ... 拷貝文件到項目目錄 } else if (type.equals("update")) { System.out.println("監聽到更新的配置,準備下載..."); // ... 連接ftp服務器,根據url找到相應的配置 Thread.sleep(500); System.out.println("開始下載配置文件,下載路徑爲<" + url + ">"); // ... 下載配置到你指定的目錄 Thread.sleep(1000); System.out.println("下載成功..."); System.out.println("刪除項目中原配置文件..."); Thread.sleep(100); // ... 刪除原文件 System.out.println("拷貝配置文件到項目目錄..."); // ... 拷貝文件到項目目錄 } else if (type.equals("delete")) { System.out.println("監聽到需要刪除配置"); System.out.println("刪除項目中原配置文件..."); } // TODO 視情況統一重啓服務 } } } } }); countDown.await(); cto.closeZKClient(); } }
- RedisConfig
package com.imooc.utils; public class RedisConfig { private String type; // add 新增配置 update 更新配置 delete 刪除配置 private String url; // 如果是add或update,則提供下載地址 private String remark; // 備註 public String getType() { return type; } public void setType(String type) { this.type = type; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }
- RedisConfig.json
{"type":"add","url":"ftp://192.168.10.123/config/redis.xml","remark":"add"} {"type":"update","url":"ftp://192.168.10.123/config/redis.xml","remark":"update"} {"type":"delete","url":"","remark":"delete"}
- linux客戶端寫入更新文件
--啓動linux客戶端 zkCli.sh [zk: localhost:2181(CONNECTED) 14] create /workspace/super/imooc/redis-config 111 Created /workspace/super/imooc/redis-config
--開始驗證
[zk: localhost:2181(CONNECTED) 16] set /workspace/super/imooc/redis-config {"type":"add","url":"ftp://192.168.10.123/config/redis.xml","remark":"add"} cZxid = 0x122 ctime = Fri Apr 12 07:06:11 CST 2024 mZxid = 0x123 mtime = Fri Apr 12 07:06:59 CST 2024 pZxid = 0x122 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 75 numChildren = 0 [zk: localhost:2181(CONNECTED) 17] set /workspace/super/imooc/redis-config {"type":"update","url":"ftp://192.168.10.123/config/redis.xml","remark":"update"} cZxid = 0x122 ctime = Fri Apr 12 07:06:11 CST 2024 mZxid = 0x124 mtime = Fri Apr 12 07:10:03 CST 2024 pZxid = 0x122 cversion = 0 dataVersion = 2 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 81 numChildren = 0 [zk: localhost:2181(CONNECTED) 18] set /workspace/super/imooc/redis-config {"type":"delete","url":"","remark":"delete"} cZxid = 0x122 ctime = Fri Apr 12 07:06:11 CST 2024 mZxid = 0x125 mtime = Fri Apr 12 07:10:54 CST 2024 pZxid = 0x122 cversion = 0 dataVersion = 3 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 44 numChildren = 0
- java所有客戶端(3個)進行更新配置文件
監聽到配置發生變化,節點路徑爲:/super/imooc/redis-config 節點/super/imooc的數據爲: {"type":"add","url":"ftp://192.168.10.123/config/redis.xml","remark":"add"} 監聽到新增的配置,準備下載... 開始下載新的配置文件,下載路徑爲<ftp://192.168.10.123/config/redis.xml> 下載成功,已經添加到項目中 監聽到配置發生變化,節點路徑爲:/super/imooc/redis-config 節點/super/imooc的數據爲: {"type":"update","url":"ftp://192.168.10.123/config/redis.xml","remark":"update"} 監聽到更新的配置,準備下載... 開始下載配置文件,下載路徑爲<ftp://192.168.10.123/config/redis.xml> 下載成功... 刪除項目中原配置文件... 拷貝配置文件到項目目錄... 監聽到配置發生變化,節點路徑爲:/super/imooc/redis-config 節點/super/imooc的數據爲: {"type":"delete","url":"","remark":"delete"} 監聽到需要刪除配置 刪除項目中原配置文件...
3.2 工具類
package com.imooc.utils; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; /** * * @Title: JsonUtils.java * @Package com.lee.utils * @Description: JSON/對象轉換類 * Copyright: Copyright (c) 2016 * Company:Nathan.Lee.Salvatore * * @author leechenxiang * @date 2016年4月29日 下午11:05:03 * @version V1.0 */ public class JsonUtils { // 定義jackson對象 private static final ObjectMapper MAPPER = new ObjectMapper(); /** * 將對象轉換成json字符串。 * <p>Title: pojoToJson</p> * <p>Description: </p> * @param data * @return */ public static String objectToJson(Object data) { try { String string = MAPPER.writeValueAsString(data); return string; } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } /** * 將json結果集轉化爲對象 * * @param jsonData json數據 * @param clazz 對象中的object類型 * @return */ public static <T> T jsonToPojo(String jsonData, Class<T> beanType) { try { T t = MAPPER.readValue(jsonData, beanType); return t; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 將json數據轉換成pojo對象list * <p>Title: jsonToList</p> * <p>Description: </p> * @param jsonData * @param beanType * @return */ public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) { JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); try { List<T> list = MAPPER.readValue(jsonData, javaType); return list; } catch (Exception e) { e.printStackTrace(); } return null; } }