All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.javaclub.configcenter.client.DefaultConfigCenterClient Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
package com.github.javaclub.configcenter.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.github.javaclub.configcenter.client.domain.CfgVO;
import com.github.javaclub.configcenter.client.util.DESCoder;
import com.github.javaclub.configcenter.client.util.HttpHelper;
import com.github.javaclub.configcenter.client.util.PropUtil;
import com.github.javaclub.configcenter.client.util.PropUtil.Configuration;
import com.github.javaclub.configcenter.client.util.Utils;

public class DefaultConfigCenterClient implements ConfigCenterClient {
	
	private static final Logger logger = LoggerFactory.getLogger(DefaultConfigCenterClient.class);
	private static String endpoint; // ip:port 如:127.0.0.1:7001
	private static ConcurrentMap appMap = new ConcurrentHashMap();
	private static ConcurrentMap> cfg = new ConcurrentHashMap>();
	private static ExecutorService exector = Executors.newFixedThreadPool(5);
	private static AtomicBoolean inited = new AtomicBoolean(false);
	private static String env;
	
	public static final String JAR_GROUP_ID = "com.github.javaclub";
	public static final String JAR_ARTIFACT_ID = "configcenter-client";
	
	/**
	 * 需要在实际项目环境 classpath:server.properties 文件种定义,如:
	 * 
	 * configserver.address=192.168.31.216:7001;192.168.31.60:7001
	 * 
*/ private static final String CONFIG_SERVER_ADDRESS = "configserver.address"; public DefaultConfigCenterClient() { String serverIps = this.ensureReady(); String[] ipArray = StringUtils.split(serverIps, ";"); for (String ipAndPort : ipArray) { if(StringUtils.isBlank(ipAndPort)) { continue; } String testUrl = "http://" + ipAndPort.trim() + "/configcenter/webStatus?timestamp=" + System.currentTimeMillis(); try { String resp = HttpHelper.get(testUrl); if(!StringUtils.equals("success", resp)) { continue; } } catch (Exception e) { logger.error("Test configcenter server address => " + ipAndPort, e); } DefaultConfigCenterClient.endpoint = ipAndPort.trim(); break; } if(Utils.isBlank(getEndpoint())) { throw new RuntimeException("No available configcenter server address in => [" + serverIps + "]"); } } String ensureReady() { Configuration conf = null; try { conf = PropUtil.getConfiguration(); } catch (Throwable e) { throw e; } if(null == conf) { throw new RuntimeException("The config file => [server.properties] not be found in classpath"); } if(Utils.isBlank(conf.getValue(CONFIG_SERVER_ADDRESS))) { throw new RuntimeException("KEY:" + CONFIG_SERVER_ADDRESS + " should be set in file => [classpath:server.properties]"); } try { env = conf.getValue("env"); } catch (Exception e) { } return conf.getValue(CONFIG_SERVER_ADDRESS); } public void init(int appid, String appkey) { if (inited.compareAndSet(false, true)) { ConfigServer.getInstance().setEndPoint(endpoint); ConfigServer.getInstance().setEnv(env); ConfigServer.getInstance().setAppid(String.valueOf(appid)); ConfigServer.getInstance().setAppkey(appkey); ConfigServer.getInstance().init(); Thread t = new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(3000L); if (!appMap.isEmpty()) { Map> queryParam = new HashMap>(); for (int appid : appMap.keySet()) { AppCfg appCfg = appMap.get(appid); queryParam.put(appCfg.appid, new HashMap()); synchronized (appCfg.lock) { for (String configkey : appCfg.configKeyList) { queryParam.get(appid).put(configkey, "0"); if (cfg.get(appid) != null && cfg.get(appid).get(configkey) != null) { queryParam.get(appid).put(configkey, cfg.get(appid).get(configkey).timestamp); } } } } if (!queryParam.isEmpty()) { if (polling(queryParam)) { // 配置有更新 for (int appid : cfg.keySet()) { // 保存文件快照 ConfigLocalSave.getInstance().snapshot(appid, appMap.get(appid).getAppkey(), cfg.get(appid).values()); } } else { for (int appid : cfg.keySet()) { // 本地无配置数据时,保存 if (null == ConfigLocalSave.getInstance().readConfigFromFile(appid, appMap.get(appid).getAppkey())) { ConfigLocalSave.getInstance().snapshot(appid, appMap.get(appid).getAppkey(), cfg.get(appid).values()); } } } } } } catch (Throwable t) { logger.error("", t); } } } }); t.setName("config-center-client"); t.setDaemon(true); t.start(); } } // 查询配置是否变更 private static boolean polling(Map> param) { StringBuilder sb = new StringBuilder(); sb.append("http://"); sb.append(ConfigServer.getInstance().getOneServer()); sb.append("/configcenter/item/query/batch?clientVer=" + getClientVersion()); boolean flag = false; try { final Map postBody = new HashMap(); for (int appid : param.keySet()) { postBody.put(appid, DESCoder.encrypt(JSONObject.toJSONString(param.get(appid)), appMap.get(appid).appkey)); } String resp = HttpHelper.post(sb.toString(), JSONObject.toJSONString(postBody)); if (StringUtils.isNotBlank(resp)) { JSONObject result = JSONObject.parseObject(resp); if (result.getShort("code") == 0) { @SuppressWarnings("unchecked") Map map = JSONObject.parseObject(result.getString("result"), Map.class); if (map != null && !map.isEmpty()) { for (final int appid : map.keySet()) { String str = DESCoder.decrpty(map.get(appid), appMap.get(appid).appkey); @SuppressWarnings("unchecked") final Map cfgMap = JSONObject.parseObject(str, Map.class); if (cfgMap != null && !cfgMap.isEmpty()) { cfg.putIfAbsent(appid, new HashMap()); for (String configkey : cfgMap.keySet()) { JSONObject jSONObject = cfgMap.get(configkey); CfgVO cfgVO = new CfgVO(jSONObject.getString("configkey"), jSONObject.getString("configvalue"), jSONObject.getString("timestamp")); cfg.get(appid).put(configkey, cfgVO); } flag = true; for (final String configkey : cfgMap.keySet()) { synchronized (appMap.get(appid).lock) { if (!appMap.get(appid).listeners.get(configkey).isEmpty()) { for (final ConfigListener configListener : appMap.get(appid).listeners.get(configkey)) { exector.submit(new Runnable() { @Override public void run() { try { JSONObject jSONObject = cfgMap.get(configkey); CfgVO cfgVO = new CfgVO(jSONObject.getString("configkey"), jSONObject .getString("configvalue"), jSONObject.getString("timestamp")); configListener.update(cfgVO.getConfigvalue()); // 触发监听器 report(false, appid, appMap.get(appid).appkey, configkey, cfgVO.getConfigvalue()); } catch (Exception e) { logger.error("", e); } } }); } } } } } } } } else { logger.error("failed to getConfig:" + resp); } } } catch (Exception e) { logger.error("", e); } return flag; } @Override public String getConfig(int appid, String appkey, String configkey, ConfigListener configListener) { if (!inited.get()) { init(appid,appkey); } appMap.putIfAbsent(appid, new AppCfg()); AppCfg appCfg = appMap.get(appid); appCfg.setAppid(appid); appCfg.setAppkey(appkey); String value = null; try { value = queryConfig(appid, appkey, configkey); } catch (Exception e) { logger.error("", e); } finally { if(value == null) { Map map = ConfigLocalSave.getInstance().get(appid, appkey, configkey); if (map != null) { value = map.get("value"); String timestamp = map.get("timestamp"); CfgVO cfgVO = new CfgVO(configkey, value, timestamp); cfg.putIfAbsent(appid, new HashMap()); cfg.get(appid).put(configkey, cfgVO); logger.warn("from local cfg:{},{},{}",appid,configkey,value); } } appCfg.addConfigKey(configkey, configListener); // 注册配置项及监听器 if(value != null) { report(true, appid, appkey, configkey, value); } else { throw new ConfigException(String.format("failed to get config: appid[%s],configkey[%s]", appid, configkey)); } } return value; } private String queryConfig(int appid, String appkey, String configkey) throws ConfigException { try { String resp = null; configkey = configkey.trim(); appkey = appkey.trim(); try { resp = doQuery(appid, appkey, configkey); } catch (Exception e) { } if(StringUtils.isBlank(resp)){ // retry Thread.sleep(1000l); resp = doQuery(appid, appkey, configkey); } if (StringUtils.isNotBlank(resp)) { JSONObject result = JSONObject.parseObject(resp); if (result.getShort("code") == 0) { if (StringUtils.isNotBlank(result.getString("result"))) { String v = DESCoder.decrpty(result.getString("result"), appkey); if (StringUtils.isNotBlank(v)) { @SuppressWarnings("unchecked") Map map = JSONObject.parseObject(v, Map.class); String value = map.get("value"); String timestamp = map.get("timestamp"); CfgVO cfgVO = new CfgVO(configkey, value, timestamp); cfg.putIfAbsent(appid, new HashMap()); cfg.get(appid).put(configkey, cfgVO); return value; } } } else { logger.error("failed to getConfig:" + resp); throw new ConfigException(resp); } } } catch (Exception e) { throw new ConfigException(e.getMessage()); } return null; } private String doQuery(int appid, String appkey, String configkey) throws Exception { final StringBuilder sb = new StringBuilder(); sb.append("http://"); sb.append(ConfigServer.getInstance().getOneServer()); sb.append("/configcenter/item/query?clientVer=" + getClientVersion()); sb.append("&appid=" + appid); sb.append("&key=" + configkey); Future future = exector.submit(new Callable() { @Override public String call() throws Exception { String resp = HttpHelper.get(sb.toString()); return resp; } }); return future.get(3, TimeUnit.SECONDS); } private static void report(boolean asyn, int appid, String appkey, String configkey, String configValue) { int retry = 2; while (retry-- > 0) { final StringBuilder sb = new StringBuilder(); sb.append("http://"); sb.append(ConfigServer.getInstance().getOneServer()); sb.append("/configcenter/report?clientVer=" + getClientVersion()); sb.append("&appid=" + appid); sb.append("&configKey=" + configkey); try { final String text = DESCoder.encrypt(configValue, appkey); Future future = exector.submit(new Callable() { @Override public String call() throws Exception { return HttpHelper.post(sb.toString(), text); } }); if (!asyn) { if ("true".equals(future.get(3, TimeUnit.SECONDS))) { return; } }else{ break; } } catch (Exception e) { logger.error("", e); } } } public String getEndpoint() { return endpoint; } public void setEndpoint(String endpoint) { DefaultConfigCenterClient.endpoint = endpoint; } public class AppCfg { public int appid; public String appkey; public List configKeyList = new ArrayList(); public Map> listeners = new HashMap>(); public Object lock = new Object(); public void addConfigKey(String configkey, ConfigListener configListener) { synchronized (lock) { if (!configKeyList.contains(configkey)) { configKeyList.add(configkey); } if (configListener != null) { if (listeners.get(configkey) == null) { listeners.put(configkey, new ArrayList()); } if (!listeners.get(configkey).contains(configListener)) { listeners.get(configkey).add(configListener); } } } } public int getAppid() { return appid; } public void setAppid(int appid) { this.appid = appid; } public String getAppkey() { return appkey; } public void setAppkey(String appkey) { this.appkey = appkey; } @Override public String toString() { return "AppCfg [appid=" + appid + ", appkey=" + appkey + ", configKeyList=" + configKeyList + ", listeners=" + listeners + ", lock=" + lock + "]"; } } @Override public boolean setConfig(int appid, String appkey, String configKey, String configValue) throws ConfigException { try { if (!inited.get()) { init(appid,appkey); } final StringBuilder sb = new StringBuilder(); sb.append("http://"); sb.append(ConfigServer.getInstance().getOneServer()); sb.append("/configcenter/item/update?clientVer=" + getClientVersion()); sb.append("&appid=" + appid); Map map = new HashMap(); map.put("key", configKey); map.put("value", configValue); final String text = DESCoder.encrypt(JSONObject.toJSONString(map), appkey); Future future = exector.submit(new Callable() { @Override public String call() throws Exception { String resp = HttpHelper.post(sb.toString(), text); return resp; } }); return "success".equals(future.get(3, TimeUnit.SECONDS)); } catch (Exception e) { throw new ConfigException(e); } } /** * 取当前客户端在使用的版本 * * @return configcenter-client版本号 */ public static String getClientVersion() { return Utils.getConfigClientVer(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy