300行的动态配置中心客户端
来源:互联网 发布:2017网络市场专项行动 编辑:程序博客网 时间:2024/05/23 19:13
300行的动态配置中心客户端
配置中心在目前service化中占着越来越重要的步骤,特别是在docker容器中。
在去年我们公司也需要一个这样的配置中心,借鉴了国内外如阿里百度配置中心。准备自己也写一个。
一开始设计的复杂的一米,可能需要一个月四五个人的开发才能完成。
但是突然的灵感,一下午就写完了,而且在线上运行了6个月80多台机器共同使用。没有一点问题。
不会挂的原因很简单,所有的配置都在zookeeper的node上,本地会加载到内存,然后写入到zookeeper的node上,zookeeper出现问题,和客户端一点问题都不相关。zookeeper的连接使用的是curator框架,并且设置3秒连接一次,无限重连。
白话文简单明了,各位线上出了问题请找我。
package com.jenkin.ec;import net.sf.json.JSONObject;import org.apache.commons.lang.StringUtils;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.CuratorFrameworkFactory;import org.apache.curator.framework.recipes.cache.NodeCache;import org.apache.curator.framework.recipes.cache.NodeCacheListener;import org.apache.curator.retry.RetryNTimes;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.Path;import org.apache.zookeeper.CreateMode;import org.codehaus.jackson.map.ObjectMapper;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.net.InetAddress;import java.net.UnknownHostException;import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantReadWriteLock;/** * Created by jenkin.z.chen on 2017/8/28. */public class ZkConf extends Configuration { private static final Log logger = LogFactory.getLog(ZkConf.class); private static CuratorFramework client; private static Configuration configuration; private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private static Lock readLock = readWriteLock.readLock(); private static Lock writeLock = readWriteLock.writeLock(); private static String listenPath; private static ZkConf zkConf; private static String absolutePath; private static int port; /** * ZkAddress is zookeeper's address * listenPath is monitor the zookeeper path * Port is the main function is to distinguish the same directory machine machine * absolutePath is Program start read file, and writes it to zookeeper * * @param zkAddress * @param listenPath * @param absolutePath * @return */ public static ZkConf getInstance(String zkAddress,String listenPath,int port,String absolutePath){ if(zkConf==null){ writeLock.lock(); try{ zkConf = new ZkConf(zkAddress,listenPath,port,absolutePath); return zkConf; }finally { writeLock.unlock(); } }else{ return zkConf; } } private ZkConf(String zkAddress,String listenerPath,int port,String absolutePath){ if(StringUtils.isBlank(zkAddress)||StringUtils.isBlank(listenerPath)){ throw new RuntimeException("[ZkError] zkAddress|listenerPath is null"); } configuration = new Configuration(); configuration.clear(); this.listenPath = listenerPath+"/"+getLocalHost()+":"+port; this.absolutePath = absolutePath; this.port = port; client = CuratorFrameworkFactory.builder().connectString(zkAddress) .sessionTimeoutMs(5000) .connectionTimeoutMs(3000) .retryPolicy(new RetryNTimes(Integer.MAX_VALUE,3000)) .build(); client.start(); init(); Thread listenThread = new Thread(new ListenRunnable()); listenThread.setDaemon(true); listenThread.start(); } /** * */ public void init(){ File file = new File(absolutePath); if(!file.exists()){ throw new RuntimeException("absolutePath not exist"); } if(!file.canWrite()&&!file.canRead()){ throw new RuntimeException("file can't read or can't write"); } try { if(client.checkExists().forPath(listenPath)!=null&&client.getData().forPath(listenPath)!=null){ writeConf(new String(client.getData().forPath(listenPath))); }else{ parseXml(); client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(listenPath,conf2Json().getBytes()); } } catch (Exception e) { e.printStackTrace(); } } public String get(String name){ readLock.lock(); try{ return configuration.get(name); }finally { readLock.unlock(); } } public String get(String name,String defaultValue){ readLock.lock(); try{ String valueString = configuration.get(name); if(valueString==null){ return defaultValue; } return valueString; }finally { readLock.unlock(); } } public String[] getStrings(String name){ readLock.lock(); try{ String str = configuration.get(name); return str.split(","); }finally { readLock.unlock(); } } public Collection<String> getStringCollection(String name){ readLock.lock(); try{ return org.apache.hadoop.util.StringUtils.getStringCollection(configuration.get(name)); }catch (Exception e){ logger.error("ZkConf getStringCollection has error!!!",e); } finally { readLock.unlock(); } return null; } public boolean containsKey(String name){ readLock.lock(); try{ return configuration.onlyKeyExists(name); }finally { readLock.unlock(); } } public int getInt(String name,int defaultValue){ readLock.lock(); try{ String valueString = configuration.get(name); if(valueString==null){ return defaultValue; } else{ try{ int valueInt = Integer.valueOf(valueString); return valueInt; }catch (Exception e){ return defaultValue; } } }finally { readLock.unlock(); } } public long getLong(String name,long defaultValue){ readLock.lock(); try { String valueString = configuration.get(name); if(valueString==null){ return defaultValue; } else{ try{ long valueInt = Integer.valueOf(valueString); return valueInt; }catch (Exception e){ return defaultValue; } } }finally { readLock.unlock(); } } public boolean getBoolean(String name,boolean defaultValue){ readLock.lock(); try{ String valueString = configuration.get(name); if(valueString==null){ return defaultValue; } else{ try{ boolean valueBoolean = Boolean.valueOf(valueString); return valueBoolean; }catch(Exception e){ return defaultValue; } } }finally { readLock.unlock(); } } public <F> Map<String,Map<String,F>> getMap(String name){ readLock.lock(); try{ String valueString = configuration.get(name); if(valueString==null){ return new HashMap<String,Map<String,F>>(); } else{ try{ ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(valueString,Map.class); }catch(Exception e){ return new HashMap<String,Map<String,F>>(); } } }finally { readLock.unlock(); } } public void set(String key,String value){ writeLock.lock(); try{ logger.info("[ZkConf] name:"+key+" has exchange,value:"+value); configuration.set(key,value); }finally { writeLock.unlock(); } } public void clear(){ writeLock.lock(); try{ logger.info("[ZkConf] Conf will to clear"); configuration.clear(); }finally { writeLock.unlock(); } } private void writeConf(String data) throws IOException { writeLock.lock(); try{ configuration.clear(); JSONObject jsonObject = JSONObject.fromObject(data); Iterator iterator = jsonObject.keys(); while(iterator.hasNext()){ String key = String.valueOf(iterator.next()); set(key,jsonObject.getString(key)); } configuration.writeXml(new FileOutputStream(new File(absolutePath))); }finally { writeLock.unlock(); } } private String conf2Json(){ readLock.lock(); try{ Iterator<Map.Entry<String, String>> iterator= configuration.iterator(); JSONObject jsonObject = new JSONObject(); while(iterator.hasNext()){ Map.Entry<String,String> entry = iterator.next(); jsonObject.put(entry.getKey(),entry.getValue()); } return jsonObject.toString(); }finally { readLock.unlock(); } } public void listen() { try{ final NodeCache loadBalance = new NodeCache(client,listenPath); loadBalance.getListenable().addListener(new NodeCacheListener() { public void nodeChanged() throws Exception { if(loadBalance.getCurrentData().getData()!=null){ writeConf(new String(loadBalance.getCurrentData().getData())); } else{ clear(); } } }); loadBalance.start(); }catch (Exception e){ logger.warn("[ZkError] start zookeeper listen has ERROR"); } } public String getLocalHost() { InetAddress inetAddress = null; String host = null; try { inetAddress = InetAddress.getLocalHost(); host = inetAddress.getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } return host; } public Iterator<Map.Entry<String, String>> iterator(){ return configuration.iterator(); } private class ListenRunnable implements Runnable{ public void run() { listen(); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { e.printStackTrace(); } } } public void parseXml(){ zkConf.addResource(new Path(absolutePath)); }}
阅读全文
0 0
- 300行的动态配置中心客户端
- SpringCloud配置中心客户端读取配置
- 我的架构之路 — 配置中心(三)— 动态更新配置
- 不要写死!天猫App的动态化配置中心实践
- zookeeper配置中心的实现
- 基于zookeeper的配置中心
- SpringCloud 简单的配置中心
- springcloud-config配置中心的安全配置
- 有赞 App 动态化配置中心实践
- 配置中心
- dubbo 的monitor监控中心 配置过程
- dubbo 的monitor监控中心配置
- dubbo 的monitor监控中心配置
- 基于zookeeper的分布式一致性配置中心
- springcloud_7(配置中心的高可用)
- spring cloud 配置中心的部署
- springcloud-config配置中心的使用
- WCF读取配置动态生成客户端对象
- 在word中方便的输入公式
- 操作帧缓冲:测试程序 struct fb_var_screeninfo struct fb_fix_screeninfo fix
- C/C++中数据类型的解析
- CodeForces 233 C.Cycles(构造)
- 简单编程注意
- 300行的动态配置中心客户端
- Spring MVC @RequestMapping注解详解
- 面向对象编程
- 古文觀止卷八_送董邵南序_韓愈
- 数据结构实验之查找五:平方之哈希表
- web开发编码问题
- android studio教程-创建第一个项目Hello World
- RNN简介
- 微信公众平台开发视频公开课第1讲-基础入门