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

来源:互联网 发布:包小姐过夜 知乎 编辑:程序博客网 时间:2024/05/23 16:10

1、使用场景

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

2、实现逻辑

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


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

3、代码实现

接入层的接口定义如下:
[java] view plain copy
  1. /** 
  2.  *  
  3.  */  
  4. package com.flykingmz.zookeeper.configyard;  
  5.   
  6. import java.util.Map;  
  7.   
  8. /** 
  9.  * 配置资源接口 
  10.  * @author flyking 
  11.  *  
  12.  */  
  13. public interface ConfigYard {  
  14.     /** 
  15.      * 配置平台根节点名称 
  16.      */  
  17.     static String yardRoot = "/yard";  
  18.       
  19.     /** 
  20.      * 初始化配置 
  21.      */  
  22.     void init();  
  23.       
  24.     /** 
  25.      * 重新加载配置资源 
  26.      */  
  27.     void reload();  
  28.       
  29.     /** 
  30.      * 添加配置 
  31.      * @param key 
  32.      * @param value 
  33.      */  
  34.     void add(String key, String value);  
  35.   
  36.     /** 
  37.      * 更新配置 
  38.      * @param key 
  39.      * @param value 
  40.      */  
  41.     void update(String key, String value);  
  42.   
  43.     /** 
  44.      * 删除配置 
  45.      * @param key 
  46.      */  
  47.     void delete(String key);  
  48.   
  49.     /** 
  50.      * 获取配置 
  51.      * @param key 
  52.      * @return 
  53.      */  
  54.     String get(String key);  
  55.   
  56.     /** 
  57.      * 获取所有的配置内容 
  58.      * @return 
  59.      */  
  60.     Map<String, String> getAll();  
  61.   
  62. }  
接口一个实现类:
[java] view plain copy
  1. /** 
  2.  *  
  3.  */  
  4. package com.flykingmz.zookeeper.configyard;  
  5.   
  6. import java.util.HashMap;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9.   
  10. import org.I0Itec.zkclient.ZkClient;  
  11. import org.slf4j.Logger;  
  12. import org.slf4j.LoggerFactory;  
  13.   
  14. /** 
  15.  * @author flyking 
  16.  *  
  17.  */  
  18. public class ProgrammaticallyConfigYard implements ConfigYard {  
  19.     private final static Logger logger = LoggerFactory  
  20.             .getLogger(ProgrammaticallyConfigYardTest.class);  
  21.     /** 
  22.      * 存储配置内容 
  23.      */  
  24.     private volatile Map<String, String> yardProperties = new HashMap<String, String>();  
  25.   
  26.     private ZkClient client;  
  27.       
  28.     private ConfigYardWatcher configYardWatcher;  
  29.   
  30.     public ProgrammaticallyConfigYard(String serverstring) {  
  31.         this.client = new ZkClient(serverstring);  
  32.         configYardWatcher = new ConfigYardWatcher(client,this);  
  33.         this.init();  
  34.     }  
  35.   
  36.     /** 
  37.      * 初始化加载配置到内存 
  38.      */  
  39.     public void init() {  
  40.         if(!client.exists(yardRoot)){  
  41.             client.createPersistent(yardRoot);  
  42.         }  
  43.         if (yardProperties == null) {  
  44.             logger.info("start to init yardProperties");  
  45.             yardProperties = this.getAll();  
  46.             logger.info("init yardProperties over");  
  47.         }  
  48.     }  
  49.   
  50.     private String contactKey(String key){  
  51.         return yardRoot.concat("/").concat(key);  
  52.     }  
  53.       
  54.     public void add(String key, String value) {  
  55.         String contactKey = this.contactKey(key);  
  56.         this.client.createPersistent(contactKey, value);  
  57.         configYardWatcher.watcher(contactKey);  
  58.     }  
  59.   
  60.     public void update(String key, String value) {  
  61.         String contactKey = this.contactKey(key);  
  62.         this.client.writeData(contactKey, value);  
  63.         configYardWatcher.watcher(contactKey);  
  64.     }  
  65.   
  66.     public void delete(String key) {  
  67.         String contactKey = this.contactKey(key);  
  68.         this.client.delete(contactKey);  
  69.     }  
  70.   
  71.     public String get(String key) {  
  72.         if(this.yardProperties.get(key) == null){  
  73.             String contactKey = this.contactKey(key);  
  74.             if(!this.client.exists(contactKey)){  
  75.                 return null;  
  76.             }  
  77.             return this.client.readData(contactKey);  
  78.         }  
  79.         return yardProperties.get(key);  
  80.     }  
  81.   
  82.     public Map<String, String> getAll() {  
  83.         if(yardProperties != null){  
  84.             return yardProperties;  
  85.         }  
  86.         List<String> yardList = this.client.getChildren(yardRoot);  
  87.         Map<String, String> currentYardProperties = new HashMap<String, String>();  
  88.         for(String yard : yardList){  
  89.             String value = this.client.readData(yard);  
  90.             String key = yard.substring(yard.indexOf("/")+1);  
  91.             currentYardProperties.put(key, value);  
  92.         }  
  93.         return yardProperties;  
  94.     }  
  95.   
  96.     public void reload() {  
  97.         List<String> yardList = this.client.getChildren(yardRoot);  
  98.         Map<String, String> currentYardProperties = new HashMap<String, String>();  
  99.         for(String yard : yardList){  
  100.             String value = this.client.readData(this.contactKey(yard));  
  101.             currentYardProperties.put(yard, value);  
  102.         }  
  103.         yardProperties = currentYardProperties;  
  104.     }  
  105.   
  106. }  
在其中使用到的一个zookeeper的监听实现类:
[java] view plain copy
  1. /** 
  2.  *  
  3.  */  
  4. package com.flykingmz.zookeeper.configyard;  
  5.   
  6. import java.util.List;  
  7.   
  8. import org.I0Itec.zkclient.IZkChildListener;  
  9. import org.I0Itec.zkclient.IZkDataListener;  
  10. import org.I0Itec.zkclient.ZkClient;  
  11. import org.slf4j.Logger;  
  12. import org.slf4j.LoggerFactory;  
  13.   
  14. /** 
  15.  * @author flyking 
  16.  *  
  17.  */  
  18. public class ConfigYardWatcher {  
  19.     private final static Logger logger = LoggerFactory  
  20.             .getLogger(ConfigYardWatcher.class);  
  21.       
  22.     private ZkClient client;  
  23.       
  24.     private ConfigYardListener configYardListener;  
  25.       
  26.     private ConfigYard configYard;  
  27.   
  28.     public ConfigYardWatcher(ZkClient client,ConfigYard configYard) {  
  29.         this.client = client;  
  30.         this.configYard = configYard;  
  31.         this.initConfigYard();  
  32.     }  
  33.       
  34.     private void initConfigYard(){  
  35.         configYardListener = new ConfigYardListener();  
  36.     }    
  37.       
  38.     public void watcher(String key){  
  39.         client.subscribeDataChanges(key, configYardListener);  
  40.         client.subscribeChildChanges(key, configYardListener);  
  41.     }  
  42.   
  43.     /** 
  44.      * 配置监听器 
  45.      * @author flyking 
  46.      * 
  47.      */  
  48.     private class ConfigYardListener implements IZkDataListener,IZkChildListener{  
  49.         public void handleDataChange(String dataPath, Object data)  
  50.                 throws Exception {  
  51.             logger.info("data {} change,start reload configProperties",dataPath);  
  52.             configYard.reload();  
  53.         }  
  54.   
  55.         public void handleDataDeleted(String dataPath) throws Exception {  
  56.             logger.info("data {} delete,start reload configProperties",dataPath);  
  57.             configYard.reload();  
  58.         }  
  59.   
  60.         public void handleChildChange(String parentPath,  
  61.                 List<String> currentChilds) throws Exception {  
  62.             logger.info("data {} ChildChange,start reload configProperties",parentPath);  
  63.             configYard.reload();  
  64.         }  
  65.           
  66.     }  
  67. }  
基于实现类的一个测试代码:
[java] view plain copy
  1. /** 
  2.  *  
  3.  */  
  4. package com.flykingmz.zookeeper.configyard;  
  5.   
  6.   
  7. import org.slf4j.Logger;  
  8. import org.slf4j.LoggerFactory;  
  9.   
  10. /** 
  11.  * @author flyking 
  12.  *  
  13.  */  
  14. public class ProgrammaticallyConfigYardTest {  
  15.     private final static Logger logger = LoggerFactory  
  16.             .getLogger(ProgrammaticallyConfigYard.class);  
  17.   
  18.     public static void main(String[] args) {  
  19.         ProgrammaticallyConfigYard yard = new ProgrammaticallyConfigYard("host:port");  
  20.         yard.add("testKey1""1");  
  21.         yard.add("testKey2""2");  
  22.         yard.add("testKey3""3");  
  23.         yard.add("testKey4""4");  
  24.         yard.add("testKey5""5");  
  25.         yard.add("testKey6""6");  
  26.         logger.info("value is===>"+yard.get("testKey1"));  
  27.         logger.info("value is===>"+yard.get("testKey2"));  
  28.         logger.info("value is===>"+yard.get("testKey3"));  
  29.         logger.info("value is===>"+yard.get("testKey4"));  
  30.         logger.info("value is===>"+yard.get("testKey5"));  
  31.         logger.info("value is===>"+yard.get("testKey6"));  
  32.         yard.update("testKey6""testKey6");  
  33.         logger.info("update testKey6 value is===>"+yard.get("testKey6"));  
  34.         yard.delete("testKey1");  
  35.         yard.delete("testKey2");  
  36.         yard.delete("testKey3");  
  37.         yard.delete("testKey4");  
  38.         yard.delete("testKey5");  
  39.         yard.delete("testKey6");  
  40.     }  
  41. }  
测试结果如下:
[html] view plain copy
  1. 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard  - value is===>1  
  2. 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard  - value is===>2  
  3. 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard  - value is===>3  
  4. 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard  - value is===>4  
  5. 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard  - value is===>5  
  6. 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard  - value is===>6  
  7. 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  
  8. 2016-10-26 14:58:39 [main] INFO com.flykingmz.zookeeper.configyard.ProgrammaticallyConfigYard  - update testKey6 value is===>testKey6  
  9. 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
0 0
原创粉丝点击