zoukankan      html  css  js  c++  java
  • ZooKeeper实践:(2)配置管理

    一、 前言

        配置是每个程序不可或缺的一部分,配置有多重方式:xml、ini、property、database等等,从最初的单机环境到现在的分布式环境。

           1. 以文件的格式存储配置,修改任何都要改程序,重新发布,重新部署,经常出现数据不一致的问题,配置错误,会造成更大的问题。

           2. 以数据库+缓存配置,解决了动态更新配置的方式,但是存在数据库的单点问题,一单数据库出现问题,更新的操作都会失败,造成配置不能持久化。

       随着机器数的增多,逐个修改配置是一件不合理的做法,使用Zookeeper可以实现数据发布与订阅,顾名思义就是把数据存储在Zookeeper的节点上,供订阅方进行获取,实现配置信息的集中式管理和动态更新。解决以上问题

    二、需求

           1. 实现集中式配置管理

           2. 实现灰度发布(先发布一台机器)

    三、技术原理

           1. 配置信息存储在Zookeeper的某个目录下中,目录的命名按照一定的规则(例如:应用ID),一组相同功能的应用集群监控一个节点。

           2. 配置发生变化,应用服务器会监听到事件,然后从Zookeeper获取新的配置信息到更新应用服务器的本地缓存中。

           3. 做一个简单的界面展示集群的所有机器,可以拉出来一台灰度发布。

           4. 应用服务器在接收到新的配置信息时判断是否是灰度发布的,如果是判断机器的IP,如果IP相同就更新本地缓存,否则不更新。

    四:架构体系

          

    五:流程图

                    

    六:相关代码 

          client模拟:

                        

    package com.zk.config.manager;
    
    import java.io.IOException;
    import java.util.concurrent.CountDownLatch;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.WatchedEvent;
    import org.apache.zookeeper.Watcher;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.Watcher.Event.EventType;
    import org.apache.zookeeper.Watcher.Event.KeeperState;
    
    
    public class App {
    	private CountDownLatch connectedSemaphore = new CountDownLatch(1);
    	private ZooKeeper zooKeeper;
    	private Object lock = new Object();
    	private String ip;
    
    	private String rootConfig;
    
    	public App(String ip, String root) {
    		this.ip = ip;
    		this.rootConfig = root;
    		this.zooKeeper = connectZookeeper();
    		
    	}
    	/**
    	 * 更新缓存
    	 * @param path
    	 * @param value
    	 */
    
    	private void updateCache(String path, String value) {
    		//System.out.println(CacheManager.get("ips"));
    		if (CacheManager.get("ips").contains(this.ip)) {
    			CacheManager.add(this.ip + path, value);
    			System.out.println(ip+"被更新了");
    		}
    	}
    	
    
    	public  ZooKeeper connectZookeeper() {
    		synchronized (lock) {
    			if (zooKeeper == null) {
    				try {
    					zooKeeper = new ZooKeeper("192.168.1.222:2181", 5000, new Watcher() {
    						public void process(WatchedEvent event) {
    							if (KeeperState.SyncConnected == event.getState()) {
    								if (EventType.None == event.getType() && null == event.getPath()) {
    									try {
    										connectedSemaphore.countDown();
    										zooKeeper.getChildren(rootConfig, true);
    									} catch (KeeperException e) {
    										e.printStackTrace();
    									} catch (InterruptedException e) {
    										e.printStackTrace();
    									}
    								} else if (EventType.NodeChildrenChanged == event.getType()) {
    									try {
    										System.out.println(ip);
    										String path = event.getPath();
    										String value  =new String(zooKeeper.getData(path, false, null));
    										zooKeeper.getChildren(rootConfig, true);
    										updateCache(path,value);//模拟更新缓存
    									} catch (KeeperException e) {
    										e.printStackTrace();
    									} catch (InterruptedException e) {
    										e.printStackTrace();
    									}
    
    								}
    
    							}
    						}
    					}
    
    					);
    					connectedSemaphore.await();
    				} catch (IOException e) {
    					e.printStackTrace();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    
    			}
    		}
    		return zooKeeper;
    	}
    }
    

          本地缓存模拟:

    package com.zk.config.manager;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    //模拟本机缓存
    public class CacheManager {
    	
    	private static Map<String, String> map = new HashMap<String, String>();
    	
    	
    	public static void add(String key,String value)
    	{
    		map.put(key, value);
    	}
    	
    	
    	public static String get(String key)
    	{
    		return map.get(key);
    	}
    
    }
    

     配置管理模拟:

              

    package com.zk.config.manager;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.ZooDefs.Ids;
    import org.apache.zookeeper.ZooKeeper;
    
    public class ConfigManager {
    
        private static String rootConfigName = "/testApp";
        public static void main(String[] args) throws KeeperException, InterruptedException {
    
            String ips = args[0]; // 要发布的机器IP
            CacheManager.add("ips", ips);
            App app1 = new App("192.168.1.1", rootConfigName);
            App app2 = new App("192.168.1.2", rootConfigName);
            App app3 = new App("192.168.1.3", rootConfigName);
            ZooKeeper zooKeeper = app1.connectZookeeper();
            zooKeeper.create(rootConfigName + "/gggggg", "sds".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            zooKeeper.delete(rootConfigName + "/gggggg", -1);
            Thread.sleep(60000);
    
        }
    }

    运行结果:
    192.168.1.3
    192.168.1.1
    192.168.1.2
    192.168.1.1被更新了          

  • 相关阅读:
    死磕Lambda表达式(四):常用的函数式接口
    死磕Lambda表达式(三):更简洁的Lambda
    死磕Lambda表达式(二):Lambda的使用
    死磕Lambda表达式(一):初识Lambda
    二叉树面试题:前中序求后序、中后序求前序
    五分钟后,你将真正理解MySQL事务隔离级别!
    详细解析Redis中的布隆过滤器及其应用
    详细解析Java虚拟机的栈帧结构
    面试真题:求100万内的质数
    C#-Xamarin的Android项目开发(一)——创建项目
  • 原文地址:https://www.cnblogs.com/programlearning/p/6841255.html
Copyright © 2011-2022 走看看