一、 前言

    配置是每个程序不可或缺的一部分,配置有多重方式: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被更新了

ZooKeeper实践:(1)配置管理的更多相关文章

  1. ZooKeeper实践:(2)配置管理

    一. 前言     配置是每个程序不可或缺的一部分,配置有多重方式:xml.ini.property.database等等,从最初的单机环境到现在的分布式环境. 1. 以文件的格式存储配置,修改任何都 ...

  2. Zookeeper实践方案:(4)命名服务

    1.基本介绍 命名服务是指通过指定的名字来获取资源或者服务的地址,提供者的信息.利用Zookeeper非常easy创建一个全局的路径,而这个路径就能够作为一个名字.它能够指向集群中的集群.提供的服务的 ...

  3. ZooKeeper实践方案:(7) 分布式锁

    1.基本介绍 分布式锁是控制分布式系统之间同步訪问共享资源的一种方式,须要相互排斥来防止彼此干扰来保证一致性. 利用Zookeeper的强一致性能够完毕锁服务.Zookeeper的官方文档是列举了两种 ...

  4. ZooKeeper实践:(2)集群管理

    前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...

  5. ZooKeeper实践:(1)集群管理

    前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...

  6. 部署zookeeper实践

    1.解压zookeeper 2.环境变量设置 hadoop@namenode:~/zookeeper-3.4.6/conf$ sudo vim /etc/profile export JAVA_HOM ...

  7. 分布式锁 ----zookeeper实践 (排它锁)

    排它锁概念: Exclusive Locks,被称为X锁,写锁,独占锁.如果事物T1对数据对象O1加上了排它锁,那么在整个加锁期间,只允许事务T1对O1进行读写操作,其他事务必须等到T1释放锁后才能进 ...

  8. 1、ZooKeeper 基本概念、使用方法、实践场景

    ZooKeeper 基本概念 ZooKeeper 是面向分布式应用的协调服务,其实现了树形结构的数据模型(与文件系统类似),并且提供了简洁的编程原语.ZooKeeper 能够作为基础,用于构建更高层级 ...

  9. Disconf实践指南:安装篇

    Disconf是百度开源出来的一款基于Zookeeper的分布式配置管理软件.目前很多公司都在使用,包括滴滴.百度.网易.顺丰等公司.通过简单的界面操作就可以动态修改配置属性,还是很方便的.使用Dis ...

随机推荐

  1. javascript的闭包与一次重构的感受

    有没有这么一个场景,你的一个动作需要在所有异步方法执行完毕后,再进行操作?然而你对异步方法何时执行完毕感到困扰,只能在每个方法中写回调,在回调中重复劳动? 偶然的,想起了之前经理讲过的闭包的概念,偶然 ...

  2. 【JavaWeb】Session(转)

    Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自 ...

  3. 编写你的第一个程序(HelloWorld)

    1)安装. 2)打开我们的编译工具Xcode,会出现一些选项,我们只需要选中第2项(因为版本不同可能有些不同)“Create a new Xcode project ”如下图(其他的选项目前我们还没有 ...

  4. jquery练习之瀑布流

    最近有空简单学习了下瀑布流,写完后想和大家一起分享下,但我知道我的代码有很多缺陷不足,希望多多包涵.(纯属兴趣非专业学习人士) 众所周知,瀑布流大概分为2种,一种是浮动式的瀑布流,一种是定位式的瀑布流 ...

  5. [SinGuLaRiTy] 字节大小

    [SinGuLaRiTy-1006] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 16位编译器 char 1个字节 char*(即指针变量 ...

  6. 手机自动化测试:Appium源码分析之跟踪代码分析八

    手机自动化测试:Appium源码分析之跟踪代码分析八   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...

  7. laravel blade $loop

    laravel 5.3 blade 新增$loop变量 文档如下: 在Laravel 5.3中,@foreach指令提供了更加强大的功能,在每一个@foreach循环体中都可以调用一个新的$loop变 ...

  8. 4月5日--课堂笔记--JS内置对象

    JavaScript 4.5 一.    JS内置对象 1.数组Array a)创建语法1:var arr=new Array(参数); i.       没有参数:创建一个初始容量为0的数组 ii. ...

  9. (转)Python 遍历List三种方式

    转自: http://www.cnblogs.com/pizitai/archive/2017/02/14/6398276.html # 方法1 print '遍历列表方法1:' for i in l ...

  10. 4 安装MPush

    cnblogs-DOC 1.服务器环境 2.安装Redis3.安装Zookeeper4.安装MPush5.安装Alloc服务6.完整测试7.常见问题 一.Linux安装Mpush [root@loca ...