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

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

The newest version!
package com.github.javaclub.configcenter.client;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
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 java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.javaclub.configcenter.ConfigServerConstants.BootConfig;
import com.github.javaclub.configcenter.ConfigServerConstants.Client;
import com.github.javaclub.configcenter.client.conf.AppCfg;
import com.github.javaclub.configcenter.client.conf.ConfigRemoveFlagHolder;
import com.github.javaclub.configcenter.client.conf.LocalConfigserverConf;
import com.github.javaclub.configcenter.client.domain.CfgVO;
import com.github.javaclub.configcenter.client.domain.ConfigChangedEvent;
import com.github.javaclub.configcenter.client.domain.ServerNode;
import com.github.javaclub.configcenter.client.domain.ServerNodeHolder;
import com.github.javaclub.configcenter.client.util.DESCoder;
import com.github.javaclub.configcenter.client.util.DingTalkUtils;
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;
import com.github.javaclub.toolbox.AppBootHook;
import com.github.javaclub.toolbox.ToolBox.ClassPath;
import com.github.javaclub.toolbox.ToolBox.Numbers;
import com.github.javaclub.toolbox.ToolBox.Objects;
import com.github.javaclub.toolbox.ToolBox.Strings;
import com.github.javaclub.toolbox.ToolBox.Systems;
import com.github.javaclub.toolbox.conf.CompositeAppConfigProperties;
import com.github.javaclub.toolbox.conf.ConfigcenterLoader;
import com.github.javaclub.toolbox.thread.ExecutorServiceInstance;
import com.github.javaclub.toolbox.utils.ThreadLocalDateFormatter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

public class DefaultConfigCenterClient implements ConfigCenterClient {
	
	private static final Logger logger = LoggerFactory.getLogger(DefaultConfigCenterClient.class);
	
	private static volatile String endpoint; // ip:port 如:127.0.0.1:7001
	private static volatile ConcurrentMap appMap = new ConcurrentHashMap();
	private static volatile ConcurrentMap> cfg = new ConcurrentHashMap>();
	
	private static volatile ExecutorService exector = Executors.newFixedThreadPool(5);
	private static volatile AtomicBoolean inited = new AtomicBoolean(false);
	private static volatile AtomicInteger pollingFailedCounter = new AtomicInteger(0);
	private static volatile int ALARM_BY_MAX_POLLING_FAILED_TIMES = 5; // 1分钟内连续集中式的有5次以上请求错误,会触发报警
	
	private static volatile String env;
	private static DefaultConfigCenterClient instance;
	
	public static DefaultConfigCenterClient getInstance() {
		if (null == instance) {
			synchronized (DefaultConfigCenterClient.class) {
				if (null == instance) {
					instance = new DefaultConfigCenterClient();
				}
			}
		}
		return instance;
	}
	
	private DefaultConfigCenterClient() {
		String serverIps = this.ensureReady();
		Systems.out("Configserver address config: {}", serverIps);
		String[] ipArray = Utils.splitAndTrim(serverIps, BootConfig.CONFIGSERVER_ADDRESS_SEPCHAR);
		int thisAppId = CompositeAppConfigProperties.getInstance().intValue(BootConfig.CONFIGSERVER_APPID, 0);
		for (String ipAndPort : ipArray) {
			if (Utils.isBlank(ipAndPort)) {
				continue;
			}
			String testUrl = Utils.concat("http://", ipAndPort.trim(),
        			"/configcenter/webStatus?startup=true×tamp=", System.currentTimeMillis(), 
        			"&clientVer=", getClientVersion(), "&env=", getEnv(), 
        			"&appName=", CompositeAppConfigProperties.getInstance().getAppName()
			);
			boolean up = false;
			try {
				String resp = HttpHelper.get(testUrl);
				up = Utils.equals("success", resp);
			} catch (Exception e) {
				if (thisAppId > 0) {
					logger.error("Test Configcenter serverAddress: {}, error: {}", ipAndPort, e.getMessage());
				}
			}
			if (up) {
				String svrIpAndPort = ipAndPort.trim();
				ServerNodeHolder.getInstance().registerNode(new ServerNode(svrIpAndPort));
				if (Utils.isBlank(getEndpoint())) {
					setEndpoint(svrIpAndPort);
					ConfigServer.getInstance().setEndPoint(svrIpAndPort);
					Systems.out("Configserver default endpoint address seleced: {}", svrIpAndPort);
				}
			}
		}
		if (thisAppId > 0) {
			if (Utils.isBlank(getEndpoint())) {
				// throw new ConfigException("No available configcenter server address in => [" + serverIps + "]");
				Systems.out("No available configcenter server address in => [" + serverIps + "]");
				if (null != ipArray && ipArray.length > 0) {
					String svrIpAndPort = ipArray[0].trim();
					setEndpoint(svrIpAndPort);
					ConfigServer.getInstance().setEndPoint(svrIpAndPort);
					Systems.out("No available serverAddress, select {} as default", svrIpAndPort);
				}
			}
			monitorPollingCounter();
		}
	}

	void monitorPollingCounter() {
		ExecutorServiceInstance.get(Client.CLIENT_WORKER_ALARM_MONITOR).scheduleAtFixedRate(() -> {
			pollingFailedCounter.set(0); // 1分钟内异常计数被重置1次
		}, 1L, 60L, TimeUnit.SECONDS);
	}

	String ensureReady() {
		CompositeAppConfigProperties appConf = CompositeAppConfigProperties.getInstance();
		boolean isLocal = appConf.boolValue(BootConfig.CONFIGSERVER_ISLOCAL);
		env = Objects.requireNotEmpty(appConf.getEnv(), "Application Environment config not found.");
		if (isLocal) {
			return String.valueOf("127.0.0.1:" + ConfigServer.CONFIG_SERVER_PORT);
		}
		// 1. 优先从本地拿配置中心地址
		String serverIps = appConf.getValue(BootConfig.CONFIGSERVER_ADDRESS);
		if (Utils.isNotBlank(serverIps)) {
			return serverIps;
		}
		// 2. 从本地server.properties配置文件中读取
		Configuration conf = null;
		try {
			conf = PropUtil.getConfiguration();
			if (null != conf && Utils.isNotBlank(conf.getValue(BootConfig.CONFIGSERVER_ADDRESS))) {
				return conf.getValue(BootConfig.CONFIGSERVER_ADDRESS);
			}
		} catch (Throwable e) {
			// throw e;
		}
		// 3. 从依赖jar包中文件: configserver-env.properties 读取配置中心地址
		Properties properties = ClassPath.readConfigFile(BootConfig.JAR_CONFIG_FILE, new Properties());
		String thisEnvAddrKey = BootConfig.getServerAddressKey();
		if (null != properties && Strings.isNotBlank(properties.getProperty(thisEnvAddrKey))) {
			String configServerAddr = properties.getProperty(thisEnvAddrKey);
			CompositeAppConfigProperties.getInstance().merge(com.github.javaclub.toolbox.ToolBox.Maps.createStringMap(
				BootConfig.CONFIGSERVER_ADDRESS, configServerAddr
			));
			if (Strings.isBlank(LocalConfigserverConf.getInstance().getServerAddress())) {
				LocalConfigserverConf.getInstance().setServerAddress(configServerAddr);
			}
			return configServerAddr;
		}
		throw new RuntimeException("Configcenter [" + BootConfig.CONFIGSERVER_ADDRESS + "] is not found.");
	}

	public void init(int appId, String appkey) {
		if (0 >= appId || Strings.isBlank(appkey)) {
			return;
		}
		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 thread = new Thread(() -> {
				while (true) {
					try {
						if (AppBootHook.isAppShuttingDown()) {
							return;
						}
						ALARM_BY_MAX_POLLING_FAILED_TIMES = CompositeAppConfigProperties.getInstance().intValue(BootConfig.CONFIGSERVER_CLIENT_POLLING_ALARM, 3);
						Thread.sleep(3000L);
						if (!appMap.isEmpty()) {
							Map> queryParam = new HashMap>();
							for (int appid : appMap.keySet()) {
								if (0 >= appid) {
									continue; // 可能没有配置任何appId 
								}
								AppCfg appCfg = appMap.get(appid);
								queryParam.putIfAbsent(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 tAppId : cfg.keySet()) { // 保存文件快照
										ConfigLocalSave.getInstance()
											.snapshot(tAppId, appMap.get(tAppId).getAppkey(), cfg.get(tAppId).values());
									}
								} else {
									for (int tAppId : cfg.keySet()) {
										// 本地无配置数据时,保存
										if (null == ConfigLocalSave.getInstance().readConfigFromFile(tAppId, appMap.get(tAppId).getAppkey())) {
											ConfigLocalSave.getInstance()
												.snapshot(tAppId, appMap.get(tAppId).getAppkey(), cfg.get(tAppId).values());
										}
									}
								}
							}
						}
					} catch (Throwable e) {
						logger.error("", e);
					}
				}
			});
			thread.setName("config-center-client");
			thread.setDaemon(true);
			thread.start();
		}
	}

	// 查询配置是否变更
	public boolean polling(Map> param) {
		StringBuilder sb = new StringBuilder();
		String ipAndPort = ConfigServer.getInstance().getOneServer();
		sb.append("http://");
		sb.append(ipAndPort);
		sb.append("/configcenter/item/query/batch?clientVer=" + getClientVersion());
		sb.append("&env=" + env);
		if (ServerNodeHolder.getInstance().isNoServersOrAllDown()) {
			return false;
		}
		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 (Utils.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 obj = cfgMap.get(configkey);
									CfgVO cfgVO = new CfgVO(obj.getString("configkey"), obj.getString("configvalue"), obj.getString("timestamp"));
									cfg.get(appid).put(configkey, cfgVO);
									if (cfgVO.isMarkedRemoved()) {
										cfg.get(appid).remove(configkey);
										logger.warn("ConfigChanged key={} is removed", configkey);
									}
								}

								flag = true;
								for (final String configkey : cfgMap.keySet()) {
									synchronized (appMap.get(appid).lock) {
										JSONObject cfgObj = cfgMap.get(configkey);
										String configvalue = cfgObj.getString("configvalue");
										String timestamp = cfgObj.getString("timestamp");
										ConfigChangedEvent event = new ConfigChangedEvent(configkey, configvalue, timestamp);
										// step1: 先触发配置变更事件监听器
										if (!appMap.get(appid).listeners.get(configkey).isEmpty()) {
											for (final ConfigChangeListener listener : appMap.get(appid).listeners.get(configkey)) {
												exector.submit(() -> {
													try {
														listener.onChange(event);
														report(true, appid, appMap.get(appid).appkey, configkey, configvalue);
													} catch (Exception e) {
														logger.error("", e);
													}
												});
											}
										}
										// step2: 再处理删除逻辑
										if (event.isRemoved()) { 
											try {
												ConfigRemoveFlagHolder.set(false); // 设置不必用同步锁
												ConfigcenterLoader.getInstance().removeMonitorKey(configkey);
											} finally {
												ConfigRemoveFlagHolder.remove();
											}
										}
									}
								}
								ConfigServer.getInstance().flagAsNormal(ipAndPort);
								if (pollingFailedCounter.get() > 0) {
									pollingFailedCounter.decrementAndGet();
								}
							}
						}
					}
				} else {
					logger.error("Failed to getConfig: " + resp);
				}
			}
		} catch (Exception e) {
			logger.error("ConfigCenterClient polling {} failed, appId={}", ipAndPort, JSON.toJSONString(param.keySet()));
			pollingFailedCounter.incrementAndGet();
			ConfigServer.getInstance().flagAsBroken(ipAndPort, System.currentTimeMillis());
			if (pollingFailedCounter.get() > ALARM_BY_MAX_POLLING_FAILED_TIMES) {
				ExecutorServiceInstance.get(Client.CLIENT_WORKER_ALARM_MONITOR).submit(() -> {
					Map map = Maps.newHashMap();
					map.put("请求地址", sb.toString());
					map.put("异常明细", Utils.lessText(e.getMessage(), 60, true));
					DingTalkUtils.sendMarkdown("ConfigCenterClient轮询异常", new Date(), map);
				});
			}
		}
		return flag;
	}

	@Override
	public String getConfig(int appid, String appkey, String configkey, ConfigChangeListener configListener) {
		if (!inited.get()) {
			init(appid, appkey);
		}
		if (0 >= appid || Strings.isBlank(appkey)) {
			return null;
		}
		appMap.putIfAbsent(appid, new AppCfg());
		appMap.get(appid).init(appid, appkey);
		String value = null;
		try {
			if (null != cfg.get(appid) && null != cfg.get(appid).get(configkey) 
					&& cfg.get(appid).get(configkey).isRecentlyFreshed()) {
				value = cfg.get(appid).get(configkey).configvalue;
				logger.info("ConfigKey={} present by localMemory\t timestamp={}", configkey, cfg.get(appid).get(configkey).parseTimestamp());
				return value;
			}
			if (ServerNodeHolder.getInstance().isNoServersOrAllDown()) { // 快速失败,走本地配置容灾
				throw new ConfigException("No available ConfigCenter ServerNodes");
			}
			value = queryConfig(appid, appkey, configkey);
		} catch (Exception e) {
			if (!ServerNodeHolder.getInstance().isNoServersOrAllDown()) {
				logger.warn("Failed to get config: configkey[{}], appid[{}]", configkey, appid);
			}
			// throw new ConfigException(String.format("Failed to get config: appid[%s], configkey[%s]", appid, configkey));
		} finally {
			if (null == value) {
				Map map = ConfigLocalSave.getInstance().get(appid, appkey, configkey);
				if (null != map) {
					value = map.get("value");
					if (logger.isDebugEnabled()) {
						logger.debug("Loading configValue from localcache: appid={}, key={}, value={}, timestamp={}", 
								appid, configkey, Strings.filter(value), 
								ThreadLocalDateFormatter.timestampFormat(new Date(Numbers.parseLong(map.get("timestamp")))));
					}
				}
			}
			appMap.get(appid).addConfigKey(configkey, configListener); // 注册配置项及监听器
			if (null != value) {
				if (Client.isClientAppInited()) { // 应用刚启动时刻, 不上报配置信息
					report(true, appid, appkey, configkey, value);
				}
			} else {
				logger.warn("Perhaps no configKey[{}] in appid[{}], query value is null", configkey, appid);
				// throw new ConfigException(String.format("failed to get config: appid[%s],configkey[%s]", appid, configkey));
			}
		}
		return value;
	}
	
	public String queryMeta(int appid, String appkey, boolean cdl, String topic) throws ConfigException {
		String apiPath = "/configcenter/config/queryMeta";
		Map queryParams = ImmutableMap.of("dataTopic", topic, "cdl", String.valueOf(cdl));
		try {
			String resp = null;
			try {
				resp = doQuery(apiPath, appid, queryParams);
			} catch (Exception e) {
			}
			if(Utils.isBlank(resp)) {  // retry
				Thread.sleep(200L);
				resp = doQuery(apiPath, appid, queryParams);
			}
			// 响应正常
			if (Utils.isNotBlank(resp)) {
				JSONObject result = JSONObject.parseObject(resp);
				if (result.getShort("code") == 0) {
					if (Utils.isNotBlank(result.getString("result"))) {
						String value = DESCoder.decrpty(result.getString("result"), appkey);
						if (Utils.isNotBlank(value)) {
							return value;
						}
					}
				}
			}
		} catch (Exception e) {
			throw new ConfigException(e.getMessage(), e);
		}
		return null;
	}

	private String queryConfig(int appid, String appkey, String configkey) throws ConfigException {
		try {
			String resp = null;
			configkey = configkey.trim();
			appkey = appkey.trim();
			Map params = ImmutableMap.of("key", configkey);
			String apiPath = "/configcenter/item/query";
			try {
				resp = doQuery(apiPath, appid, params);
			} catch (Exception e) {
			}
			if (Utils.isBlank(resp)) {  // retry
				Thread.sleep(Numbers.random(5L, 30L));
				resp = doQuery(apiPath, appid, params);
			}

			if (Utils.isNotBlank(resp)) {
				JSONObject result = JSONObject.parseObject(resp);
				if (result.getShort("code") == 0) {
					if (Utils.isNotBlank(result.getString("result"))) {
						String v = DESCoder.decrpty(result.getString("result"), appkey);
						if (Utils.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(), e);
		}
		return null;
	}
	
	public String doQueryKeys(int appId) throws Exception {
		final StringBuilder sb = new StringBuilder();
		String currentApp = CompositeAppConfigProperties.getInstance().getAppName();
		sb.append("http://");
		sb.append(ConfigServer.getInstance().getOneServer());
		sb.append("/configcenter/item/queryKeys?clientVer=" + getClientVersion());
		sb.append("&env=" + getEnv());
		sb.append("&appid=" + appId);
		sb.append(Utils.isBlank(currentApp) ? "" : ("&appName=" + currentApp));
		
		if (ServerNodeHolder.getInstance().isNoServersOrAllDown()) {
			// 本地容灾处理
			String resp = ConfigLocalSave.getInstance().readLocalAppConfigKeys(appId);
			logger.warn("ConfigCenter read AppConfigKeys from localcache backup, appId={}", appId);
			return resp;
		}

		Future future = exector.submit(new Callable() {
			@Override
			public String call() throws Exception {
				String resp = HttpHelper.get(sb.toString());
				return resp;
			}
		});
		return future.get(Numbers.random(3, 5), TimeUnit.SECONDS);
	}
	
	public void doPost(boolean async, String appid, String appkey, String topic, 
			Map urlParams, String postJson) throws Exception {
		String currentAppName = CompositeAppConfigProperties.getInstance().getAppName();
		final StringBuilder sb = new StringBuilder();
		sb.append("http://{}");
		sb.append("/configcenter/applyRequest?clientVer=" + getClientVersion());
		sb.append("&env=" + getEnv());
		sb.append("&appid=" + appid);
		if (Utils.isNotBlank(currentAppName)) {
			sb.append("&appName=" + currentAppName);
		}
		sb.append("&requestTopic=" + topic);
		if(null != urlParams && !urlParams.isEmpty()) {
			for (Map.Entry elem : urlParams.entrySet()) {
				if (Utils.isNotBlank(elem.getKey())) {
					sb.append(Utils.concat("&", elem.getKey(), "=", HttpHelper.urlencode(elem.getValue())));
				}
			}
		}
		String urlFormat = sb.toString();
		int retry = 3;
		while (retry-- > 0) {
			try {
				final String text = DESCoder.encrypt(postJson, appkey);
				Future future = exector.submit(new Callable() {
					@Override
					public String call() throws Exception {
						String url = Strings.format(urlFormat, ConfigServer.getInstance().getOneServer());
						return HttpHelper.post(url, text);
					}
				});
				if (!async) { // 设置了同步,才会多次执行
					if ("true".equals(future.get(3, TimeUnit.SECONDS))) {
						return;
					}
				} else { // 设置了异步,仅会执行1次
					break;
				}
			} catch (Exception e) {
				logger.error("", e);
			}
		}
	}
	
	private String doQuery(String apiPath, int appid, Map queryParams) throws Exception {
		String currentApp = CompositeAppConfigProperties.getInstance().getAppName();
		final StringBuilder sbf = new StringBuilder();
		sbf.append("http://").append(ConfigServer.getInstance().getOneServer());
		sbf.append(apiPath + "?clientVer=" + getClientVersion());
		sbf.append("&env=" + getEnv());
		sbf.append("&appid=" + appid);
		sbf.append(Utils.isBlank(currentApp) ? "" : ("&appName=" + currentApp));
		if(null != queryParams && !queryParams.isEmpty()) {
			for (Map.Entry elem : queryParams.entrySet()) {
				if (Utils.isNotBlank(elem.getKey())) {
					sbf.append(Utils.concat("&", elem.getKey(), "=", HttpHelper.urlencode(elem.getValue())));
				}
			}
		}

		Future future = exector.submit(new Callable() {
			@Override
			public String call() throws Exception {
				String resp = HttpHelper.get(sbf.toString());
				return resp;
			}
		});
		return future.get(6, TimeUnit.SECONDS);
	}
	
	public void report(boolean async, int appid, String appkey, String configkey, String configValue) {
		String currentAppName = CompositeAppConfigProperties.getInstance().getAppName();
		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("&env=" + getEnv());
			sb.append("&appid=" + appid);
			sb.append("&configKey=" + configkey);
			if (Utils.isNotBlank(currentAppName)) {
				sb.append("&appName=" + currentAppName);
			}
			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 (!async) {
					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;
	}
	
	@Override
	public String getEnv() {
		return DefaultConfigCenterClient.env;
	}
	
	public AppCfg getAppCfg(int appId) {
		if (null != appMap) {
			return appMap.get(appId);
		}
		return null;
	}
	
	@Override
	public boolean removeConfig(int appId, String appKey, String configKey) {
		if (null != cfg && null != cfg.get(appId)) {
			if (cfg.get(appId).containsKey(configKey)) {
				cfg.get(appId).remove(configKey);
			}
		}
		if (null != appMap && null != appMap.get(appId)) {
			appMap.get(appId).removeConfigKey(configKey);
		}
		return true;
	}

	@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("&env=" + getEnv());
			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();
	}

	public static void main(String[] args) {
		//
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy