Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,41 @@
import static io.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_CSE_PREFIX;
import static io.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_SERVICECOMB_PREFIX;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.EnvironmentConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConcurrentMapConfiguration;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicConfiguration;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicWatchedConfiguration;
import com.netflix.config.PollResult;
import com.netflix.config.PolledConfigurationSource;
import com.netflix.config.WatchedConfigurationSource;
import com.netflix.config.WatchedUpdateListener;
import com.netflix.config.WatchedUpdateResult;

import io.servicecomb.config.archaius.scheduler.NeverStartPollingScheduler;
import io.servicecomb.config.archaius.sources.ConfigModel;
import io.servicecomb.config.archaius.sources.MicroserviceConfigLoader;
import io.servicecomb.config.archaius.sources.MicroserviceConfigurationSource;
import io.servicecomb.config.spi.ConfigCenterConfigurationSource;
import io.servicecomb.foundation.common.utils.SPIServiceUtils;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.EnvironmentConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class ConfigUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigUtil.class);

private static final Logger LOGGER = LoggerFactory.getLogger(ConfigUtil.class);

private static final String configCenterUrlKey = "cse.config.client.serverUri";
protected static final String configCenterUrlKey = "cse.config.client.serverUri";

private static final String MICROSERVICE_CONFIG_LOADER_KEY = "cse-microservice-config-loader";

private ConfigUtil() {
private ConfigUtil() {
}

public static Object getProperty(String key) {
Expand Down Expand Up @@ -82,114 +81,92 @@ public static MicroserviceConfigLoader getMicroserviceConfigLoader(Configuration
return (MicroserviceConfigLoader) getProperty(config, MICROSERVICE_CONFIG_LOADER_KEY);
}

public static DynamicConfiguration createConfigFromYamlFile(List<ConfigModel> configModelList) {
// configuration from yaml files: default microservice.yaml
return new DynamicConfiguration(
new MicroserviceConfigurationSource(configModelList),
new NeverStartPollingScheduler());
}

public static AbstractConfiguration createConfig(List<ConfigModel> configModelList) {
DynamicConfiguration configFromYamlFile = createConfigFromYamlFile(configModelList);
return createConfig(configFromYamlFile, null);
}

public static AbstractConfiguration createConfig(DynamicConfiguration configFromYamlFile,
DynamicWatchedConfiguration configFromConfigCenter) {
// create a hierarchy of configuration that makes
// 1) dynamic configuration source override system properties
ConcurrentCompositeConfiguration config = new ConcurrentCompositeConfiguration();

if (configFromConfigCenter != null) {
ConcurrentMapConfiguration injectConfig = new ConcurrentMapConfiguration();
public static ConcurrentCompositeConfiguration createLocalConfig() {
MicroserviceConfigLoader loader = new MicroserviceConfigLoader();
loader.loadAndSort();

duplicateServiceCombConfigToCse(config, configFromConfigCenter, "configCenterConfig");
config.addConfiguration(injectConfig, "extraInjectConfig");
LOGGER.info("create local config:");
for (ConfigModel configModel : loader.getConfigModels()) {
LOGGER.info(" {}.", configModel.getUrl());
}

configFromConfigCenter.getSource().addUpdateListener(new ServiceCombPropertyUpdateListener(injectConfig));
ConcurrentCompositeConfiguration config = ConfigUtil.createLocalConfig(loader.getConfigModels());
ConfigUtil.setMicroserviceConfigLoader(config, loader);
return config;
}

duplicateServiceCombConfigToCse(config, new ConcurrentMapConfiguration(new SystemConfiguration()),
"configFromSystem");

duplicateServiceCombConfigToCse(config, new ConcurrentMapConfiguration(new EnvironmentConfiguration()),
"configFromEnvironment");
public static ConcurrentCompositeConfiguration createLocalConfig(List<ConfigModel> configModelList) {
ConcurrentCompositeConfiguration config = new ConcurrentCompositeConfiguration();

duplicateServiceCombConfigToCse(config, configFromYamlFile, "configFromYamlFile");
duplicateServiceCombConfigToCse(config,
new ConcurrentMapConfiguration(new SystemConfiguration()),
"configFromSystem");
duplicateServiceCombConfigToCse(config,
new ConcurrentMapConfiguration(new EnvironmentConfiguration()),
"configFromEnvironment");
duplicateServiceCombConfigToCse(config,
new DynamicConfiguration(
new MicroserviceConfigurationSource(configModelList), new NeverStartPollingScheduler()),
"configFromYamlFile");

return config;
}
return config;
}

//inject a copy of cse.xxx for servicecomb.xxx
private static void duplicateServiceCombConfigToCse(
ConcurrentCompositeConfiguration compositeConfiguration,
AbstractConfiguration source,
String sourceName) {
//inject a copy of cse.xxx for servicecomb.xxx
private static void duplicateServiceCombConfigToCse(AbstractConfiguration source) {
Iterator<String> keys = source.getKeys();
while (keys.hasNext()) {
String key = keys.next();
if (!key.startsWith(CONFIG_SERVICECOMB_PREFIX)) {
continue;
}

Map<String, String> injects = new HashMap<>();
Iterator<String> keys = source.getKeys();
while (keys.hasNext()) {
String key = keys.next();
if (key.startsWith(CONFIG_SERVICECOMB_PREFIX)) {
injects.put(key, CONFIG_CSE_PREFIX + key.substring(key.indexOf(".") + 1));
}
String cseKey = CONFIG_CSE_PREFIX + key.substring(key.indexOf(".") + 1);
source.addProperty(cseKey, source.getProperty(key));
}
}

compositeConfiguration.addConfiguration(source, sourceName);
private static void duplicateServiceCombConfigToCse(ConcurrentCompositeConfiguration compositeConfiguration,
AbstractConfiguration source,
String sourceName) {
duplicateServiceCombConfigToCse(source);

for (String key : injects.keySet()) {
source.addProperty(injects.get(key), source.getString(key));
compositeConfiguration.addConfiguration(source, sourceName);
}
}

public static DynamicWatchedConfiguration createConfigFromConfigCenter(
PolledConfigurationSource polledConfigurationSource) {
// configuration from config center
// Need to check whether the config center has been defined
Map<String, Object> configMap;
try {
PollResult result = polledConfigurationSource.poll(true, null);
configMap = result.getComplete();
} catch (Exception e) {
configMap = new HashMap<String, Object>();
}
DynamicWatchedConfiguration configFromConfigCenter = null;
if (configMap.get(configCenterUrlKey) != null) {
WatchedConfigurationSource configCenterConfigurationSource =
SPIServiceUtils.getTargetService(WatchedConfigurationSource.class);
if (null != configCenterConfigurationSource) {
// configuration from config center
configFromConfigCenter =
new DynamicWatchedConfiguration(configCenterConfigurationSource);
} else {
LOGGER.info(
"config center SPI service can not find, skip to load configuration from config center");
}
} else {

public static DynamicWatchedConfiguration createConfigFromConfigCenter(Configuration localConfiguration) {
if (localConfiguration.getProperty(configCenterUrlKey) == null) {
LOGGER.info("config center URL is missing, skip to load configuration from config center");
return null;
}
return configFromConfigCenter;
}

public static AbstractConfiguration createDynamicConfig(MicroserviceConfigLoader loader) {
LOGGER.info("create dynamic config:");
for (ConfigModel configModel : loader.getConfigModels()) {
LOGGER.info(" {}.", configModel.getUrl());
ConfigCenterConfigurationSource configCenterConfigurationSource =
SPIServiceUtils.getTargetService(ConfigCenterConfigurationSource.class);
if (null == configCenterConfigurationSource) {
LOGGER.info(
"config center SPI service can not find, skip to load configuration from config center");
return null;
}
DynamicConfiguration configFromYamlFile = ConfigUtil.createConfigFromYamlFile(loader.getConfigModels());
DynamicWatchedConfiguration configFromConfigCenter =
createConfigFromConfigCenter(configFromYamlFile.getSource());
return ConfigUtil.createConfig(configFromYamlFile, configFromConfigCenter);

configCenterConfigurationSource.init(localConfiguration);
return new DynamicWatchedConfiguration(configCenterConfigurationSource);
}

public static AbstractConfiguration createDynamicConfig() {
MicroserviceConfigLoader loader = new MicroserviceConfigLoader();
loader.loadAndSort();
LOGGER.info("create dynamic config:");
ConcurrentCompositeConfiguration config = ConfigUtil.createLocalConfig();
DynamicWatchedConfiguration configFromConfigCenter = createConfigFromConfigCenter(config);
if (configFromConfigCenter != null) {
ConcurrentMapConfiguration injectConfig = new ConcurrentMapConfiguration();
config.addConfigurationAtFront(injectConfig, "extraInjectConfig");

AbstractConfiguration dynamicConfig = createDynamicConfig(loader);
ConfigUtil.setMicroserviceConfigLoader(dynamicConfig, loader);
duplicateServiceCombConfigToCse(configFromConfigCenter);
config.addConfigurationAtFront(configFromConfigCenter, "configCenterConfig");

return dynamicConfig;
configFromConfigCenter.getSource().addUpdateListener(new ServiceCombPropertyUpdateListener(injectConfig));
}

return config;
}

public static void installDynamicConfig() {
Expand All @@ -202,44 +179,44 @@ public static void installDynamicConfig() {
ConfigurationManager.install(dynamicConfig);
}

private static class ServiceCombPropertyUpdateListener implements WatchedUpdateListener {

private final ConcurrentMapConfiguration injectConfig;
private static class ServiceCombPropertyUpdateListener implements WatchedUpdateListener {

ServiceCombPropertyUpdateListener(ConcurrentMapConfiguration injectConfig) {
this.injectConfig = injectConfig;
}
private final ConcurrentMapConfiguration injectConfig;

@Override
public void updateConfiguration(WatchedUpdateResult watchedUpdateResult) {
Map<String, Object> adds = watchedUpdateResult.getAdded();
if (adds != null) {
for (String add : adds.keySet()) {
if (add.startsWith(CONFIG_SERVICECOMB_PREFIX)) {
String key = CONFIG_CSE_PREFIX + add.substring(add.indexOf(".") + 1);
injectConfig.addProperty(key, adds.get(add));
}
ServiceCombPropertyUpdateListener(ConcurrentMapConfiguration injectConfig) {
this.injectConfig = injectConfig;
}
}

Map<String, Object> deletes = watchedUpdateResult.getDeleted();
if (deletes != null) {
for (String delete : deletes.keySet()) {
if (delete.startsWith(CONFIG_SERVICECOMB_PREFIX)) {
injectConfig.clearProperty(CONFIG_CSE_PREFIX + delete.substring(delete.indexOf(".") + 1));
}
}
}

Map<String, Object> changes = watchedUpdateResult.getChanged();
if (changes != null) {
for (String change : changes.keySet()) {
if (change.startsWith(CONFIG_SERVICECOMB_PREFIX)) {
String key = CONFIG_CSE_PREFIX + change.substring(change.indexOf(".") + 1);
injectConfig.setProperty(key, changes.get(change));
}

@Override
public void updateConfiguration(WatchedUpdateResult watchedUpdateResult) {
Map<String, Object> adds = watchedUpdateResult.getAdded();
if (adds != null) {
for (String add : adds.keySet()) {
if (add.startsWith(CONFIG_SERVICECOMB_PREFIX)) {
String key = CONFIG_CSE_PREFIX + add.substring(add.indexOf(".") + 1);
injectConfig.addProperty(key, adds.get(add));
}
}
}

Map<String, Object> deletes = watchedUpdateResult.getDeleted();
if (deletes != null) {
for (String delete : deletes.keySet()) {
if (delete.startsWith(CONFIG_SERVICECOMB_PREFIX)) {
injectConfig.clearProperty(CONFIG_CSE_PREFIX + delete.substring(delete.indexOf(".") + 1));
}
}
}

Map<String, Object> changes = watchedUpdateResult.getChanged();
if (changes != null) {
for (String change : changes.keySet()) {
if (change.startsWith(CONFIG_SERVICECOMB_PREFIX)) {
String key = CONFIG_CSE_PREFIX + change.substring(change.indexOf(".") + 1);
injectConfig.setProperty(key, changes.get(change));
}
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2017 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.servicecomb.config.spi;

import org.apache.commons.configuration.Configuration;

import com.netflix.config.WatchedConfigurationSource;

public interface ConfigCenterConfigurationSource extends WatchedConfigurationSource {
void init(Configuration localConfiguration);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2017 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.servicecomb.config;

import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicProperty;
import com.netflix.config.DynamicPropertyFactory;

import mockit.Deencapsulation;

// copy from other project
// this utils useful for unit tests, but now there is no project to own it.
public class ArchaiusUtils {
public static void resetConfig() {
Deencapsulation.setField(ConfigurationManager.class, "instance", null);
Deencapsulation.setField(ConfigurationManager.class, "customConfigurationInstalled", false);
Deencapsulation.setField(DynamicPropertyFactory.class, "config", null);
Deencapsulation.setField(DynamicPropertyFactory.class, "initializedWithDefaultConfig", false);
Deencapsulation.setField(DynamicProperty.class, "dynamicPropertySupportImpl", null);
}
}
Loading