一、 前言

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

最新文章

  1. UVA&amp;&amp;POJ离散概率与数学期望入门练习[4]
  2. C#的提交表单方式主要有两种WebClient与HttpWebRequest
  3. 关于Servlet手动配置web.xml部分代码
  4. MongoDB的索引(三)
  5. [问题2014S04] 复旦高等代数II(13级)每周一题(第四教学周)
  6. 二维码识别 android app
  7. 保存带有emoji的文本报错解决方案
  8. SOM自组织映射网络 教程
  9. 多校3- RGCDQ 分类: 比赛 HDU 2015-07-31 10:50 2人阅读 评论(0) 收藏
  10. 写一个Windows上的守护进程(7)捕获异常并生成dump
  11. Subsets 【dfs】
  12. 数据验证validator 与 DWZ
  13. SQL SERVER – Import CSV File Into SQL Server Using Bulk Insert – Load Comma Delimited File Into SQL Server
  14. linux挂载分区
  15. KMP算法中的next数组求解示意图
  16. Integer比较值的时候小心使用
  17. Hive导出复杂数据到csv文件
  18. iOS中类单例方法的一种实现
  19. 消息中间件之一:RabbitMQ
  20. 手推C3算法

热门文章

  1. 当在浏览器地址栏里输入URL后会发生什么事情
  2. 【Egret】Wing3发布移动APP功能,打包APK流程以及会遇到的问题
  3. 手机自动化测试:appium源码分析之bootstrap四
  4. 微信小程序首页总结
  5. AndroidAnnotations框架简单使用方法
  6. jquery之each遍历list列表
  7. sublime Text3插件无法安装解决方法(提示There are no packages available installation)
  8. 自动生成数学题型三 (框架Struts2)题型如 a+b=c(a、b、c都为分数)
  9. Python 装饰器装饰类中的方法
  10. cmd中关闭windows2008错误弹窗