您的位置:首页 > 其它

Zookeeper系列(三十)Zookeeper场景应用之配置管理中心

2017-05-15 14:07 639 查看


1、使用场景

配置中心一般用作系统的参数配置,它需要满足如下几个要求:高效获取、实时感知、分布式访问。对于一些少量频次访问的场景我们可以使用mysql数据库实现,但是有些参数在系统中访问频次较高,甚至是接口每访问一次就需要调起获取一次,特别在是大规模系统访问量的情况下,我们就需要一个高效获取实时感知的分布式配置中心。本章节我们使用zookeeper来实现一个分布式配置管理中心组件。


2、实现逻辑

实现的架构图如下所示,采取数据加载到内存方式解决高效获取的问题,借助zookeeper的节点监听机制来实现实时感知。



实现的逻辑流程图如下:分为新增配置,获取配置,删除配置。修改配置和删除配置的逻辑是一致的。




3、代码实现

接入层的接口定义如下:

[java] view
plain copy

/**

*

*/

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();

}

接口一个实现类:

[java] view
plain copy

/**

*

*/

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;

}

}

在其中使用到的一个zookeeper的监听实现类:

[java] view
plain copy

/**

*

*/

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();

}

}

}

基于实现类的一个测试代码:

[java] view
plain copy

/**

*

*/

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");

}

}

测试结果如下:

[html] view
plain copy

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

本系统的实现源码可以从https://github.com/flykingmz/zookeeper-step获取,具体的项目名称为:configYard
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: