基于zookeeper实现配置中心

基于zookeeper实现配置中心

api使用的是curator
不知道curator的同学 请移步:https://blog.csdn.net/qq_33449307/article/details/100562669

实现配置中心有两种模式:push pull

**实现原理:**zookeeper采用的是推拉相结合的方式.客户端向服务端注册自己需要关注的节点.一旦节点数据发生变化.那么服务器端就会向客户端发送watcher事件通知.客户端收到通知后,主动向服务器端更新数据.

适合用配置中心管理的数据的特点:
1.数据量比较小
2.数据内容在运行时发生动态变更
3.集群中的各个机器共享配置

代码实现 解释都在代码里 一看就明白了

public class Config {
    private final static String CONNECTSTRING = "39.105.157.149:2181," +
                                                "39.105.157.149:2182," +
                                                "39.105.157.149:2183," +
                                                "39.105.157.149:2184";
    private static final String CONFIG_PREFIX = "/config";
    public static CuratorFramework curatorFramework = null;
    //充当缓存
    private Map<String, String> cache = new HashMap<>();

    //初始化zookeeper连接
    public static synchronized CuratorFramework getInstance() {
        if (curatorFramework == null) {
            curatorFramework = CuratorFrameworkFactory.builder()
                    .connectString(CONNECTSTRING)
                    .sessionTimeoutMs(1000)
                    .connectionTimeoutMs(1000)
                    .retryPolicy(new ExponentialBackoffRetry(1000, 1000))
                    .build();
            curatorFramework.start();
        }
        return curatorFramework;
    }

    public Config() {
        this.curatorFramework = Config.getInstance();
        this.init();
    }

    //监听配置
    public void init() {
        try {
            //获取连接
            curatorFramework = Config.getInstance();
            //获取CONFIG_PREFIX的子节点 并将数据保存到缓存中
            curatorFramework.getChildren().forPath(CONFIG_PREFIX).stream().forEach(k -> {
                try {
                    String value = new String(curatorFramework.getData().forPath(CONFIG_PREFIX + "/" + k));
                    cache.put(k, value);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            //绑定一个监听 cacheData设为true 当事件发生后可以拿到节点发送的内容
            //使该配置文件的每个应用机器都需要坚挺  这里只用于演示
            PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework, CONFIG_PREFIX, true);
            //添加监听
            pathChildrenCache.getListenable().addListener((curatorFramework1, pathChildrenCacheEvent) -> {
                String path = pathChildrenCacheEvent.getData().getPath();
                //判断节点是否以制定开头开始
                if (path.startsWith(CONFIG_PREFIX)) {
                    String key = path.replace(CONFIG_PREFIX + "/", "");
                    switch (pathChildrenCacheEvent.getType()) {
                        case CHILD_ADDED:
                        case CHILD_UPDATED:   //添加节点或者修改节点数据时   修改缓存数据
                            cache.put(key, new String(pathChildrenCacheEvent.getData().getData()));
                            break;
                        case CHILD_REMOVED:  //节点删除时  从缓存中删除数据
                            cache.remove(key);
                            break;

                    }
                    if (PathChildrenCacheEvent.Type.CHILD_ADDED.equals(pathChildrenCacheEvent.getType()) ||
                            PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(pathChildrenCacheEvent.getType())) {
                        cache.put(key, new String(pathChildrenCacheEvent.getData().getData()));
                    }
                    // 子节点被删除时 从缓存中删除
                    if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(pathChildrenCacheEvent.getType())) {
                        cache.remove(key);
                    }
                }
            });
            //启动监听
            pathChildrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);//POST_INITIALIZED_EVENT模式 会刷新缓存
        } catch (Exception e) {

        }
    }

    //保存配置信息
    public void save(String name, String value) throws Exception {
        curatorFramework = Config.getInstance();
        String path = CONFIG_PREFIX + "/" + name;
        //判断节点是否存在 如果不存在就创建
        Stat stat = curatorFramework.checkExists().forPath(path);
        if (stat == null) //如果不存在该节点就创建
            curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path);

        curatorFramework.setData().forPath(path, value.getBytes());
        //缓存中存入数据
        cache.put(name, value);

    }

    //获取配置信息
    public String getCacheConfig(String name) {
        return cache.get(name);
    }


    //测试main方法
    public static void main(String[] args) throws Exception {
        Config config = new Config();
        // 模拟一个配置项,实际生产中会在系统初始化时从配置文件中加载进来
        config.save("timeout", "2000");
        for (int i = 0; i < 100; i++) {
            System.out.println(config.getCacheConfig("timeout"));
            TimeUnit.SECONDS.sleep(3);//每隔三秒打印一次
        }
    }
    

}

这里注意 为了检测修改节点数据 需使用其他客户端修改 我们这边会看到数据修改了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值