Zookeeper(Curator)实现集群配置文件统一管理

统一监听管理的优势?

因为懒, 减轻运维人员的负担, 防止由于疏忽导致集群配置文件出错.

解决思路

  1. 把公共配置抽取出来
  2. 对公共配置进行维护
  3. 修改公共配置后应用不需要重新部署

采用方案

  1. 公共配置抽取存放于zookeeper中并落地数据库

  2. 对公共配置修改后发布到zookeeper中并落地数据库

  3. 对应用开启配置实时监听,zookeeper配置文件一旦被修改,应用可实时监听到并获取
    在这里插入图片描述

利用ZK监控节点的值来通信, 监听update信号, 内容永远都是json

ConfigBean

package com.bestksl.configFileWatcherDemo.configBean;

public class RedisConfig {

    String type;
    String url;
    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;
    }
}

模拟监听watcher

package com.bestksl.configFileWatcherDemo.configWatcher;

import com.alibaba.fastjson.JSON;
import com.bestksl.configFileWatcherDemo.Path.MyPath;
import com.bestksl.configFileWatcherDemo.configBean.RedisConfig;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONUtil;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;

@Slf4j
public class ConfigWatcher implements PathChildrenCacheListener {


    @Override
    public void childEvent(CuratorFramework zkCli, PathChildrenCacheEvent event) throws Exception {
        if (event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)) {
            if (event.getData().getPath().equals(MyPath.CONFIG_ROOT + MyPath.REDIS_CONFIG)) {
                String configString = new String(event.getData().getData());
                log.info("节点信息为: {}", configString);
                RedisConfig redisConfig = JSON.parseObject(configString, RedisConfig.class);
                if (redisConfig != null) {
                    String type = redisConfig.getType();
                    String url = redisConfig.getUrl();
                    String remark = redisConfig.getRemark();
                    switch (type) {
                        case "add":
                            log.info("监听到新增的配置文件 准备下载" + url);
                            break;
                        case "delete":
                            log.info("监听到删除的配置文件 准备删除" + url);
                            break;
                        case "update":
                            log.info("监听到更新的配置文件 准备更新" + url);
                            break;
                    }
                }
            }

        }
    }
}

模拟client 1~N

大家可以复制多份模拟集群

package com.bestksl.configFileWatcherDemo.client;

import com.bestksl.configFileWatcherDemo.Path.MyPath;
import com.bestksl.configFileWatcherDemo.configWatcher.ConfigWatcher;
import com.bestksl.tools.ZkTools2;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;

import java.util.concurrent.CountDownLatch;

@Slf4j
public class Client1 {
    static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {
        ZkTools2 zkTools = new ZkTools2();
        CuratorFramework zkCli = zkTools.getCurator();
        PathChildrenCache pathChildrenCache = new PathChildrenCache(zkCli, MyPath.CONFIG_ROOT, true);
        pathChildrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);

        if (pathChildrenCache.getListenable().size() > 0) {
            log.info("wrong number of listener");
            return;
        }
        pathChildrenCache.getListenable().addListener(new ConfigWatcher());

        countDownLatch.await();

    }
}

初始化节点类

package com.bestksl.configFileWatcherDemo;

import com.bestksl.tools.ZkTools2;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;

public class SetNode {
    static String json1 = "{\"type\":\"add\",\"url\":\"ftp://110:110:110:110/config/redis.xml\",\"remark\":\"666\"}";
    static String json2 = "{\"type\":\"delete\",\"url\":\"ftp://110:110:110:110/config/redis.xml\",\"remark\":\"666\"}";
    static String json3 = "{\"type\":\"update\",\"url\":\"ftp://110:110:110:110/config/redis.xml\",\"remark\":\"666\"}";

    public static void main(String[] args) throws Exception {
        ZkTools2 zkTools = new ZkTools2();
        CuratorFramework zkCli = zkTools.getCurator();
        zkCli.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/config/redis", json1.getBytes());
        Thread.sleep(1000 * 3600);
    }
}




ZKTools工具类

package com.bestksl.tools;


import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

public class ZkTools2 {

    private String zkAddr = "192.168.1.101:2181,192.168.1.102:2181,192.168.1.103:2181";

    private int connectTimeout = 10000;

    public CuratorFramework getCurator() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(connectTimeout, 3);
        CuratorFramework client = CuratorFrameworkFactory.newClient(zkAddr, retryPolicy);
        client.start();
        return client;
    }



}

运行结果

22:31:16.322 [main-SendThread(192.168.1.103:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeDataChanged path:/config/redis for session id 0x30001f7eadb001e
22:31:16.339 [main-SendThread(192.168.1.103:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x30001f7eadb001e, packet:: clientPath:/config/redis serverPath:/config/redis finished:false header:: 9,4  replyHeader:: 9,42949677639,0  request:: '/config/redis,T  response:: #7b2274797065223a22757064617465222c2275726c223a226674703a2f2f3131303a3131303a3131303a3131302f636f6e6669672f72656469732e786d6c222c2272656d61726b223a22363636227d,s{42949677629,42949677639,1587262610496,1587263476303,3,0,0,144121699762307091,79,0,42949677629} 
22:31:16.345 [Curator-PathChildrenCache-0] INFO com.bestksl.configFileWatcherDemo.configWatcher.ConfigWatcher - 节点信息为: {"type":"update","url":"ftp://110:110:110:110/config/redis.xml","remark":"666"}
22:31:16.438 [Curator-PathChildrenCache-0] INFO com.bestksl.configFileWatcherDemo.configWatcher.ConfigWatcher - 监听到更新的配置文件 准备更新ftp://110:110:110:110/config/redis.xml
22:31:29.680 [main-SendThread(192.168.1.103:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x30001f7eadb001e after 2ms.
22:31:42.969 [main-SendThread(192.168.1.103:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x30001f7eadb001e
22:31:42.969 [main-SendThread(192.168.1.103:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeDataChanged path:/config/redis for session id 0x30001f7eadb001e
22:31:42.971 [main-SendThread(192.168.1.103:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x30001f7eadb001e after 2ms.
22:31:42.972 [main-SendThread(192.168.1.103:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x30001f7eadb001e, packet:: clientPath:/config/redis serverPath:/config/redis finished:false header:: 10,4  replyHeader:: 10,42949677640,0  request:: '/config/redis,T  response:: #7b2274797065223a2264656c657465222c2275726c223a226674703a2f2f3131303a3131303a3131303a3131302f636f6e6669672f72656469732e786d6c222c2272656d61726b223a22363636227d,s{42949677629,42949677640,1587262610496,1587263502962,4,0,0,144121699762307091,79,0,42949677629} 
22:31:42.974 [Curator-PathChildrenCache-0] INFO com.bestksl.configFileWatcherDemo.configWatcher.ConfigWatcher - 节点信息为: {"type":"delete","url":"ftp://110:110:110:110/config/redis.xml","remark":"666"}
22:31:42.974 [Curator-PathChildrenCache-0] INFO com.bestksl.configFileWatcherDemo.configWatcher.ConfigWatcher - 监听到删除的配置文件 准备删除ftp://110:110:110:110/config/redis.xml
22:31:56.310 [main-SendThread(192.168.1.103:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x30001f7eadb001e after 0ms.
原创文章 280 获赞 464 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_33709508/article/details/105613644