中間件 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;
    }
    
}

 











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