Skip to content

Commit

Permalink
Merge pull request #1470 from nobodyiam/config-source
Browse files Browse the repository at this point in the history
add getSourceType api
  • Loading branch information
nobodyiam committed Sep 16, 2018
2 parents ffc99dd + 17236f1 commit 9e3aec5
Show file tree
Hide file tree
Showing 16 changed files with 268 additions and 41 deletions.
@@ -1,5 +1,6 @@
package com.ctrip.framework.apollo;

import com.ctrip.framework.apollo.enums.ConfigSourceType;
import com.google.common.base.Function;

import java.util.Date;
Expand Down Expand Up @@ -203,4 +204,11 @@ public interface Config {
* @return the property value
*/
public <T> T getProperty(String key, Function<String, T> function, T defaultValue);

/**
* Return the config's source type, i.e. where is the config loaded from
*
* @return the config's source type
*/
public ConfigSourceType getSourceType();
}
@@ -1,6 +1,7 @@
package com.ctrip.framework.apollo;

import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.ctrip.framework.apollo.enums.ConfigSourceType;

/**
* @author Jason Song(song_s@ctrip.com)
Expand Down Expand Up @@ -36,4 +37,19 @@ public interface ConfigFile {
* @param listener the config file change listener
*/
void addChangeListener(ConfigFileChangeListener listener);

/**
* Remove the change listener
*
* @param listener the specific config change listener to remove
* @return true if the specific config change listener is found and removed
*/
public boolean removeChangeListener(ConfigChangeListener listener);

/**
* Return the config's source type, i.e. where is the config loaded from
*
* @return the config's source type
*/
public ConfigSourceType getSourceType();
}
@@ -0,0 +1,18 @@
package com.ctrip.framework.apollo.enums;

/**
* To indicate the config's source type, i.e. where is the config loaded from
*/
public enum ConfigSourceType {
REMOTE("Loaded from remote config service"), LOCAL("Loaded from local cache"), NONE("Load failed");

private final String description;

ConfigSourceType(String description) {
this.description = description;
}

public String getDescription() {
return description;
}
}
@@ -1,5 +1,7 @@
package com.ctrip.framework.apollo.internals;

import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.enums.ConfigSourceType;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
Expand All @@ -25,10 +27,12 @@
public abstract class AbstractConfigFile implements ConfigFile, RepositoryChangeListener {
private static final Logger logger = LoggerFactory.getLogger(AbstractConfigFile.class);
private static ExecutorService m_executorService;
protected ConfigRepository m_configRepository;
protected String m_namespace;
protected AtomicReference<Properties> m_configProperties;
private List<ConfigFileChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();
protected final ConfigRepository m_configRepository;
protected final String m_namespace;
protected final AtomicReference<Properties> m_configProperties;
private final List<ConfigFileChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();

private volatile ConfigSourceType m_sourceType = ConfigSourceType.NONE;

static {
m_executorService = Executors.newCachedThreadPool(ApolloThreadFactory
Expand All @@ -45,6 +49,7 @@ public AbstractConfigFile(String namespace, ConfigRepository configRepository) {
private void initialize() {
try {
m_configProperties.set(m_configRepository.getConfig());
m_sourceType = m_configRepository.getSourceType();
} catch (Throwable ex) {
Tracer.logError(ex);
logger.warn("Init Apollo Config File failed - namespace: {}, reason: {}.",
Expand Down Expand Up @@ -74,6 +79,7 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
String oldValue = getContent();

update(newProperties);
m_sourceType = m_configRepository.getSourceType();

String newValue = getContent();

Expand All @@ -97,6 +103,16 @@ public void addChangeListener(ConfigFileChangeListener listener) {
}
}

@Override
public boolean removeChangeListener(ConfigChangeListener listener) {
return m_listeners.remove(listener);
}

@Override
public ConfigSourceType getSourceType() {
return m_sourceType;
}

private void fireConfigChange(final ConfigFileChangeEvent changeEvent) {
for (final ConfigFileChangeListener listener : m_listeners) {
m_executorService.submit(new Runnable() {
Expand Down
@@ -1,5 +1,6 @@
package com.ctrip.framework.apollo.internals;

import com.ctrip.framework.apollo.enums.ConfigSourceType;
import java.util.Properties;

/**
Expand Down Expand Up @@ -29,4 +30,11 @@ public interface ConfigRepository {
* @param listener the listener to remove
*/
public void removeChangeListener(RepositoryChangeListener listener);

/**
* Return the config's source type, i.e. where is the config loaded from
*
* @return the config's source type
*/
public ConfigSourceType getSourceType();
}
@@ -1,5 +1,6 @@
package com.ctrip.framework.apollo.internals;

import com.ctrip.framework.apollo.enums.ConfigSourceType;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
Expand Down Expand Up @@ -30,10 +31,12 @@
public class DefaultConfig extends AbstractConfig implements RepositoryChangeListener {
private static final Logger logger = LoggerFactory.getLogger(DefaultConfig.class);
private final String m_namespace;
private Properties m_resourceProperties;
private AtomicReference<Properties> m_configProperties;
private ConfigRepository m_configRepository;
private RateLimiter m_warnLogRateLimiter;
private final Properties m_resourceProperties;
private final AtomicReference<Properties> m_configProperties;
private final ConfigRepository m_configRepository;
private final RateLimiter m_warnLogRateLimiter;

private volatile ConfigSourceType m_sourceType = ConfigSourceType.NONE;

/**
* Constructor.
Expand All @@ -52,7 +55,7 @@ public DefaultConfig(String namespace, ConfigRepository configRepository) {

private void initialize() {
try {
m_configProperties.set(m_configRepository.getConfig());
updateConfig(m_configRepository.getConfig(), m_configRepository.getSourceType());
} catch (Throwable ex) {
Tracer.logError(ex);
logger.warn("Init Apollo Local Config failed - namespace: {}, reason: {}.",
Expand Down Expand Up @@ -105,6 +108,11 @@ public Set<String> getPropertyNames() {
return stringPropertyNames(properties);
}

@Override
public ConfigSourceType getSourceType() {
return m_sourceType;
}

private Set<String> stringPropertyNames(Properties properties) {
//jdk9以下版本Properties#enumerateStringProperties方法存在性能问题,keys() + get(k) 重复迭代, jdk9之后改为entrySet遍历.
Map<String, String> h = new HashMap<>();
Expand All @@ -123,10 +131,12 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
if (newProperties.equals(m_configProperties.get())) {
return;
}

ConfigSourceType sourceType = m_configRepository.getSourceType();
Properties newConfigProperties = new Properties();
newConfigProperties.putAll(newProperties);

Map<String, ConfigChange> actualChanges = updateAndCalcConfigChanges(newConfigProperties);
Map<String, ConfigChange> actualChanges = updateAndCalcConfigChanges(newConfigProperties, sourceType);

//check double checked result
if (actualChanges.isEmpty()) {
Expand All @@ -138,7 +148,13 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
Tracer.logEvent("Apollo.Client.ConfigChanges", m_namespace);
}

private Map<String, ConfigChange> updateAndCalcConfigChanges(Properties newConfigProperties) {
private void updateConfig(Properties newConfigProperties, ConfigSourceType sourceType) {
m_configProperties.set(newConfigProperties);
m_sourceType = sourceType;
}

private Map<String, ConfigChange> updateAndCalcConfigChanges(Properties newConfigProperties,
ConfigSourceType sourceType) {
List<ConfigChange> configChanges =
calcPropertyChanges(m_namespace, m_configProperties.get(), newConfigProperties);

Expand All @@ -153,7 +169,7 @@ private Map<String, ConfigChange> updateAndCalcConfigChanges(Properties newConfi
}

//2. update m_configProperties
m_configProperties.set(newConfigProperties);
updateConfig(newConfigProperties, sourceType);
clearConfigCache();

//3. use getProperty to update configChange's new value and calc the final changes
Expand Down
@@ -1,5 +1,6 @@
package com.ctrip.framework.apollo.internals;

import com.ctrip.framework.apollo.enums.ConfigSourceType;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
Expand Down Expand Up @@ -38,6 +39,8 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
private volatile Properties m_fileProperties;
private volatile ConfigRepository m_upstream;

private volatile ConfigSourceType m_sourceType = ConfigSourceType.LOCAL;

/**
* Constructor.
*
Expand Down Expand Up @@ -104,14 +107,19 @@ public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) {
upstreamConfigRepository.addChangeListener(this);
}

@Override
public ConfigSourceType getSourceType() {
return m_sourceType;
}

@Override
public void onRepositoryChange(String namespace, Properties newProperties) {
if (newProperties.equals(m_fileProperties)) {
return;
}
Properties newFileProperties = new Properties();
newFileProperties.putAll(newProperties);
updateFileProperties(newFileProperties);
updateFileProperties(newFileProperties, m_upstream.getSourceType());
this.fireRepositoryChange(namespace, newProperties);
}

Expand All @@ -129,6 +137,7 @@ protected void sync() {
try {
transaction.addData("Basedir", m_baseDir.getAbsolutePath());
m_fileProperties = this.loadFromLocalCacheFile(m_baseDir, m_namespace);
m_sourceType = ConfigSourceType.LOCAL;
transaction.setStatus(Transaction.SUCCESS);
} catch (Throwable ex) {
Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex));
Expand All @@ -140,6 +149,7 @@ protected void sync() {
}

if (m_fileProperties == null) {
m_sourceType = ConfigSourceType.NONE;
throw new ApolloConfigException(
"Load config from local config failed!", exception);
}
Expand All @@ -150,8 +160,7 @@ private boolean trySyncFromUpstream() {
return false;
}
try {
Properties properties = m_upstream.getConfig();
updateFileProperties(properties);
updateFileProperties(m_upstream.getConfig(), m_upstream.getSourceType());
return true;
} catch (Throwable ex) {
Tracer.logError(ex);
Expand All @@ -162,7 +171,8 @@ private boolean trySyncFromUpstream() {
return false;
}

private synchronized void updateFileProperties(Properties newProperties) {
private synchronized void updateFileProperties(Properties newProperties, ConfigSourceType sourceType) {
this.m_sourceType = sourceType;
if (newProperties.equals(m_fileProperties)) {
return;
}
Expand Down
@@ -1,5 +1,6 @@
package com.ctrip.framework.apollo.internals;

import com.ctrip.framework.apollo.enums.ConfigSourceType;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -47,21 +48,22 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
private static final Logger logger = LoggerFactory.getLogger(RemoteConfigRepository.class);
private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);
private static final Joiner.MapJoiner MAP_JOINER = Joiner.on("&").withKeyValueSeparator("=");
private ConfigServiceLocator m_serviceLocator;
private HttpUtil m_httpUtil;
private ConfigUtil m_configUtil;
private RemoteConfigLongPollService remoteConfigLongPollService;
private static final Escaper pathEscaper = UrlEscapers.urlPathSegmentEscaper();
private static final Escaper queryParamEscaper = UrlEscapers.urlFormParameterEscaper();

private final ConfigServiceLocator m_serviceLocator;
private final HttpUtil m_httpUtil;
private final ConfigUtil m_configUtil;
private final RemoteConfigLongPollService remoteConfigLongPollService;
private volatile AtomicReference<ApolloConfig> m_configCache;
private final String m_namespace;
private final static ScheduledExecutorService m_executorService;
private AtomicReference<ServiceDTO> m_longPollServiceDto;
private AtomicReference<ApolloNotificationMessages> m_remoteMessages;
private RateLimiter m_loadConfigRateLimiter;
private AtomicBoolean m_configNeedForceRefresh;
private SchedulePolicy m_loadConfigFailSchedulePolicy;
private Gson gson;
private static final Escaper pathEscaper = UrlEscapers.urlPathSegmentEscaper();
private static final Escaper queryParamEscaper = UrlEscapers.urlFormParameterEscaper();
private final AtomicReference<ServiceDTO> m_longPollServiceDto;
private final AtomicReference<ApolloNotificationMessages> m_remoteMessages;
private final RateLimiter m_loadConfigRateLimiter;
private final AtomicBoolean m_configNeedForceRefresh;
private final SchedulePolicy m_loadConfigFailSchedulePolicy;
private final Gson gson;

static {
m_executorService = Executors.newScheduledThreadPool(1,
Expand Down Expand Up @@ -105,6 +107,11 @@ public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) {
//remote config doesn't need upstream
}

@Override
public ConfigSourceType getSourceType() {
return ConfigSourceType.REMOTE;
}

private void schedulePeriodicRefresh() {
logger.debug("Schedule periodic refresh with interval: {} {}",
m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit());
Expand Down

0 comments on commit 9e3aec5

Please sign in to comment.