ZooKeeper实践:(1)配置管理
一、 前言
配置是每个程序不可或缺的一部分,配置有多重方式: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)配置管理的更多相关文章
- ZooKeeper实践:(2)配置管理
一. 前言 配置是每个程序不可或缺的一部分,配置有多重方式:xml.ini.property.database等等,从最初的单机环境到现在的分布式环境. 1. 以文件的格式存储配置,修改任何都 ...
- Zookeeper实践方案:(4)命名服务
1.基本介绍 命名服务是指通过指定的名字来获取资源或者服务的地址,提供者的信息.利用Zookeeper非常easy创建一个全局的路径,而这个路径就能够作为一个名字.它能够指向集群中的集群.提供的服务的 ...
- ZooKeeper实践方案:(7) 分布式锁
1.基本介绍 分布式锁是控制分布式系统之间同步訪问共享资源的一种方式,须要相互排斥来防止彼此干扰来保证一致性. 利用Zookeeper的强一致性能够完毕锁服务.Zookeeper的官方文档是列举了两种 ...
- ZooKeeper实践:(2)集群管理
前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...
- ZooKeeper实践:(1)集群管理
前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...
- 部署zookeeper实践
1.解压zookeeper 2.环境变量设置 hadoop@namenode:~/zookeeper-3.4.6/conf$ sudo vim /etc/profile export JAVA_HOM ...
- 分布式锁 ----zookeeper实践 (排它锁)
排它锁概念: Exclusive Locks,被称为X锁,写锁,独占锁.如果事物T1对数据对象O1加上了排它锁,那么在整个加锁期间,只允许事务T1对O1进行读写操作,其他事务必须等到T1释放锁后才能进 ...
- 1、ZooKeeper 基本概念、使用方法、实践场景
ZooKeeper 基本概念 ZooKeeper 是面向分布式应用的协调服务,其实现了树形结构的数据模型(与文件系统类似),并且提供了简洁的编程原语.ZooKeeper 能够作为基础,用于构建更高层级 ...
- Disconf实践指南:安装篇
Disconf是百度开源出来的一款基于Zookeeper的分布式配置管理软件.目前很多公司都在使用,包括滴滴.百度.网易.顺丰等公司.通过简单的界面操作就可以动态修改配置属性,还是很方便的.使用Dis ...
随机推荐
- cookie设置今日不提醒功能
需求:为了实现 退出页面时 [启动今日不提醒]的功能.采用纯js.cookie来实现. /****今日不提醒 start *****/ var userid = <%=UserId %>; ...
- 转接口IC ADV7280/ADV7280-M:CVBS转MIPI转接口芯片 10位、4倍过采样标清电视视频解码器,支持去隔行
概述ADV7280/ADV7280-M是功能丰富的单芯片.多格式视频解码器.ADV7280/ADV7280-M可自动检测标准模拟基带视频信号,兼容复合.S视频和分量视频形式的NTSC.PAL和SECA ...
- net.sz.framework 框架 轻松搭建数据服务中心----读写分离数据一致性,滑动缓存
前言 前文讲述了net.sz.framework 框架的基础实现功能,本文主讲 net.sz.framework.db 和 net.sz.framework.szthread; net.sz.fram ...
- 利用sub lr,lr,#4:程序是如何进行返回的?
1: ARM采用的是3级流水线 ARM的流水线结构为: 取指 -----> 译码 ------> 执行 ARM代码: PC PC- ...
- vue项目目录介绍
Vue项目目录 初始化项目 vue init webpack []projectname] cd [projectname] npm install vue run dev 目录树 +---build ...
- C/C++常考面试题(一)
这算是一个系列吧,记录一下在准备秋招期间,所准备的C++面试题,望秋招顺利.所有的面试题均来源于各大论坛,网络. C/C++常考面试题(一) 常用的C++数据结构有哪些? vector,序列式容器,相 ...
- xshell配色Solarized Dark
转自:xshell配色Solarized Dark [Solarized_Dark] text(bold)= magenta(bold)=6c71c4 text= white(bold)=fdf6e3 ...
- JS前端数据格式化
当我们从后台取了数据,但是我们希望在前台统一显示格式时,我们可能需要格式化数据. 今天正好总结一下前端JS格式化数据的几个方法: 1. toFixed() 方法 可把 Number 四舍五入为指定 ...
- MSMQ队列学习记录
微软消息队列-MicroSoft Message Queue(MSMQ) 使用感受:简单. 一.windows安装MSMQ服务 控制面板->控制面板->所有控制面板项->程序和功能- ...
- 这可能是php世界中最好的日志库——monolog
由于一些历史原因,php中并没有内建的日志接口,故长期以来也没一个功能完备并且应用广泛的日志库.在我的工作生涯中,如果系统需要记录一些应用日志的话,基本上就是封装一个日志类,然后把一些要记录的字段写入 ...