中间件 ZK分布式专题与Dubbo微服务入门 7-9 zk-watcher实例 统一更新N台节点的配置文件

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

 











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