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; } }
诸葛