Zookeeper系列(三十)Zookeeper场景应用之配置管理中心
1、使用场景
配置中心一般用作系统的参数配置,它需要满足如下几个要求:高效获取、实时感知、分布式访问。对于一些少量频次访问的场景我们可以使用mysql数据库实现,但是有些参数在系统中访问频次较高,甚至是接口每访问一次就需要调起获取一次,特别在是大规模系统访问量的情况下,我们就需要一个高效获取实时感知的分布式配置中心。本章节我们使用zookeeper来实现一个分布式配置管理中心组件。
2、实现逻辑
实现的架构图如下所示,采取数据加载到内存方式解决高效获取的问题,借助zookeeper的节点监听机制来实现实时感知。
实现的逻辑流程图如下:分为新增配置,获取配置,删除配置。修改配置和删除配置的逻辑是一致的。
3、代码实现
接入层的接口定义如下:- /**
- *
- */
- package com.flykingmz.zookeeper.configyard;
- import java.util.Map;
- /**
- * 配置资源接口
- * @author flyking
- *
- */
- public interface ConfigYard {
- /**
- * 配置平台根节点名称
- */
- static String yardRoot = "/yard";
- /**
- * 初始化配置
- */
- void init();
- /**
- * 重新加载配置资源
- */
- void reload();
- /**
- * 添加配置
- * @param key
- * @param value
- */
- void add(String key, String value);
- /**
- * 更新配置
- * @param key
- * @param value
- */
- void update(String key, String value);
- /**
- * 删除配置
- * @param key
- */
- void delete(String key);
- /**
- * 获取配置
- * @param key
- * @return
- */
- String get(String key);
- /**
- * 获取所有的配置内容
- * @return
- */
- Map<String, String> getAll();
- }
- /**
- *
- */
- package com.flykingmz.zookeeper.configyard;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.I0Itec.zkclient.ZkClient;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- /**
- * @author flyking
- *
- */
- public class ProgrammaticallyConfigYard implements ConfigYard {
- private final static Logger logger = LoggerFactory
- .getLogger(ProgrammaticallyConfigYardTest.class);
- /**
- * 存储配置内容
- */
- private volatile Map<String, String> yardProperties = new HashMap<String, String>();
- private ZkClient client;
- private ConfigYardWatcher configYardWatcher;
- public ProgrammaticallyConfigYard(String serverstring) {
- this.client = new ZkClient(serverstring);
- configYardWatcher = new ConfigYardWatcher(client,this);
- this.init();
- }
- /**
- * 初始化加载配置到内存
- */
- public void init() {
- if(!client.exists(yardRoot)){
- client.createPersistent(yardRoot);
- }
- if (yardProperties == null) {
- logger.info("start to init yardProperties");
- yardProperties = this.getAll();
- logger.info("init yardProperties over");
- }
- }
- private String contactKey(String key){
- return yardRoot.concat("/").concat(key);
- }
- public void add(String key, String value) {
- String contactKey = this.contactKey(key);
- this.client.createPersistent(contactKey, value);
- configYardWatcher.watcher(contactKey);
- }
- public void update(String key, String value) {
- String contactKey = this.contactKey(key);
- this.client.writeData(contactKey, value);
- configYardWatcher.watcher(contactKey);
- }
- public void delete(String key) {
- String contactKey = this.contactKey(key);
- this.client.delete(contactKey);
- }
- public String get(String key) {
- if(this.yardProperties.get(key) == null){
- String contactKey = this.contactKey(key);
- if(!this.client.exists(contactKey)){
- return null;
- }
- return this.client.readData(contactKey);
- }
- return yardProperties.get(key);
- }
- public Map<String, String> getAll() {
- if(yardProperties != null){
- return yardProperties;
- }
- List<String> yardList = this.client.getChildren(yardRoot);
- Map<String, String> currentYardProperties = new HashMap<String, String>();
- for(String yard : yardList){
- String value = this.client.readData(yard);
- String key = yard.substring(yard.indexOf("/")+1);
- currentYardProperties.put(key, value);
- }
- return yardProperties;
- }
- public void reload() {
- List<String> yardList = this.client.getChildren(yardRoot);
- Map<String, String> currentYardProperties = new HashMap<String, String>();
- for(String yard : yardList){
- String value = this.client.readData(this.contactKey(yard));
- currentYardProperties.put(yard, value);
- }
- yardProperties = currentYardProperties;
- }
- }
- /**
- *
- */
- package com.flykingmz.zookeeper.configyard;
- import java.util.List;
- import org.I0Itec.zkclient.IZkChildListener;
- import org.I0Itec.zkclient.IZkDataListener;
- import org.I0Itec.zkclient.ZkClient;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- /**
- * @author flyking
- *
- */
- public class ConfigYardWatcher {
- private final static Logger logger = LoggerFactory
- .getLogger(ConfigYardWatcher.class);
- private ZkClient client;
- private ConfigYardListener configYardListener;
- private ConfigYard configYard;
- public ConfigYardWatcher(ZkClient client,ConfigYard configYard) {
- this.client = client;
- this.configYard = configYard;
- this.initConfigYard();
- }
- private void initConfigYard(){
- configYardListener = new ConfigYardListener();
- }
- public void watcher(String key){
- client.subscribeDataChanges(key, configYardListener);
- client.subscribeChildChanges(key, configYardListener);
- }
- /**
- * 配置监听器
- * @author flyking
- *
- */
- private class ConfigYardListener implements IZkDataListener,IZkChildListener{
- public void handleDataChange(String dataPath, Object data)
- throws Exception {
- logger.info("data {} change,start reload configProperties",dataPath);
- configYard.reload();
- }
- public void handleDataDeleted(String dataPath) throws Exception {
- logger.info("data {} delete,start reload configProperties",dataPath);
- configYard.reload();
- }
- public void handleChildChange(String parentPath,
- List<String> currentChilds) throws Exception {
- logger.info("data {} ChildChange,start reload configProperties",parentPath);
- configYard.reload();
- }
- }
- }
- /**
- *
- */
- package com.flykingmz.zookeeper.configyard;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- /**
- * @author flyking
- *
- */
- public class ProgrammaticallyConfigYardTest {
- private final static Logger logger = LoggerFactory
- .getLogger(ProgrammaticallyConfigYard.class);
- public static void main(String[] args) {
- ProgrammaticallyConfigYard yard = new ProgrammaticallyConfigYard("host:port");
- yard.add("testKey1", "1");
- yard.add("testKey2", "2");
- yard.add("testKey3", "3");
- yard.add("testKey4", "4");
- yard.add("testKey5", "5");
- yard.add("testKey6", "6");
- logger.info("value is===>"+yard.get("testKey1"));
- logger.info("value is===>"+yard.get("testKey2"));
- logger.info("value is===>"+yard.get("testKey3"));
- logger.info("value is===>"+yard.get("testKey4"));
- logger.info("value is===>"+yard.get("testKey5"));
- logger.info("value is===>"+yard.get("testKey6"));
- yard.update("testKey6", "testKey6");
- logger.info("update testKey6 value is===>"+yard.get("testKey6"));
- yard.delete("testKey1");
- yard.delete("testKey2");
- yard.delete("testKey3");
- yard.delete("testKey4");
- yard.delete("testKey5");
- yard.delete("testKey6");
- }
- }
- 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard - value is===>1
- 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard - value is===>2
- 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard - value is===>3
- 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard - value is===>4
- 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard - value is===>5
- 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard - value is===>6
- 2016-10-26 14:58:39 [ZkClient-EventThread-9-172.16.10.58:2181] INFO com.flykingmz.zookeeper.configyard.ConfigYardWatcher - data /yard/testKey6 change,start reload configProperties
- 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard - update testKey6 value is===>testKey6
- 2016-10-26 14:58:39 [ZkClient-EventThread-9-172.16.10.58:2181] INFO com.flykingmz.zookeeper.configyard.ConfigYardWatcher - data /yard/testKey6 delete,start reload configProperties