Skip to content

Commit

Permalink
Add OrderedProperties to keep the property order in apollo-client
Browse files Browse the repository at this point in the history
  • Loading branch information
songdragon authored and nobodyiam committed Jan 21, 2020
1 parent 42edb9d commit 82790e5
Show file tree
Hide file tree
Showing 26 changed files with 652 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.ctrip.framework.apollo.tracer.Tracer;
import com.ctrip.framework.apollo.tracer.spi.Transaction;
import com.ctrip.framework.apollo.util.ConfigUtil;
import com.ctrip.framework.apollo.util.factory.PropertiesFactory;
import com.ctrip.framework.apollo.util.function.Functions;
import com.ctrip.framework.apollo.util.parser.Parsers;
import com.google.common.base.Function;
Expand Down Expand Up @@ -58,6 +59,8 @@ public abstract class AbstractConfig implements Config {
private final List<Cache> allCaches;
private final AtomicLong m_configVersion; //indicate config version

protected PropertiesFactory propertiesFactory;

static {
m_executorService = Executors.newCachedThreadPool(ApolloThreadFactory
.create("Config", true));
Expand All @@ -68,6 +71,7 @@ public AbstractConfig() {
m_configVersion = new AtomicLong();
m_arrayCache = Maps.newConcurrentMap();
allCaches = Lists.newArrayList();
propertiesFactory = ApolloInjector.getInstance(PropertiesFactory.class);
}

@Override
Expand Down Expand Up @@ -493,11 +497,11 @@ private boolean isConfigChangeListenerInterested(ConfigChangeListener configChan
List<ConfigChange> calcPropertyChanges(String namespace, Properties previous,
Properties current) {
if (previous == null) {
previous = new Properties();
previous = propertiesFactory.getPropertiesInstance();
}

if (current == null) {
current = new Properties();
current = propertiesFactory.getPropertiesInstance();
}

Set<String> previousKeys = previous.stringPropertyNames();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.ctrip.framework.apollo.internals;

import com.ctrip.framework.apollo.build.ApolloInjector;
import com.ctrip.framework.apollo.enums.ConfigSourceType;
import com.ctrip.framework.apollo.util.factory.PropertiesFactory;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
Expand Down Expand Up @@ -30,6 +32,7 @@ public abstract class AbstractConfigFile implements ConfigFile, RepositoryChange
protected final String m_namespace;
protected final AtomicReference<Properties> m_configProperties;
private final List<ConfigFileChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();
protected final PropertiesFactory propertiesFactory;

private volatile ConfigSourceType m_sourceType = ConfigSourceType.NONE;

Expand All @@ -42,6 +45,7 @@ public AbstractConfigFile(String namespace, ConfigRepository configRepository) {
m_configRepository = configRepository;
m_namespace = namespace;
m_configProperties = new AtomicReference<>();
propertiesFactory = ApolloInjector.getInstance(PropertiesFactory.class);
initialize();
}

Expand Down Expand Up @@ -72,7 +76,7 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
if (newProperties.equals(m_configProperties.get())) {
return;
}
Properties newConfigProperties = new Properties();
Properties newConfigProperties = propertiesFactory.getPropertiesInstance();
newConfigProperties.putAll(newProperties);

String oldValue = getContent();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.ctrip.framework.apollo.internals;

import com.ctrip.framework.apollo.build.ApolloInjector;
import com.ctrip.framework.apollo.util.factory.PropertiesFactory;
import java.util.List;
import java.util.Properties;

Expand All @@ -16,6 +18,7 @@
public abstract class AbstractConfigRepository implements ConfigRepository {
private static final Logger logger = LoggerFactory.getLogger(AbstractConfigRepository.class);
private List<RepositoryChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();
protected PropertiesFactory propertiesFactory = ApolloInjector.getInstance(PropertiesFactory.class);

protected boolean trySync() {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
Expand Down Expand Up @@ -88,7 +88,7 @@ public String getProperty(String key, String defaultValue) {

// step 4: check properties file from classpath
if (value == null && m_resourceProperties != null) {
value = (String) m_resourceProperties.get(key);
value = (String) m_resourceProperties.getProperty(key);
}

if (value == null && m_configProperties.get() == null && m_warnLogRateLimiter.tryAcquire()) {
Expand All @@ -115,7 +115,7 @@ public ConfigSourceType getSourceType() {

private Set<String> stringPropertyNames(Properties properties) {
//jdk9以下版本Properties#enumerateStringProperties方法存在性能问题,keys() + get(k) 重复迭代, jdk9之后改为entrySet遍历.
Map<String, String> h = new HashMap<>();
Map<String, String> h = new LinkedHashMap<>();
for (Map.Entry<Object, Object> e : properties.entrySet()) {
Object k = e.getKey();
Object v = e.getValue();
Expand All @@ -133,7 +133,7 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
}

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

Map<String, ConfigChange> actualChanges = updateAndCalcConfigChanges(newConfigProperties, sourceType);
Expand Down Expand Up @@ -213,7 +213,7 @@ private Properties loadFromResource(String namespace) {
Properties properties = null;

if (in != null) {
properties = new Properties();
properties = propertiesFactory.getPropertiesInstance();

try {
properties.load(in);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import com.ctrip.framework.apollo.spi.DefaultConfigRegistry;
import com.ctrip.framework.apollo.tracer.Tracer;
import com.ctrip.framework.apollo.util.ConfigUtil;
import com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory;
import com.ctrip.framework.apollo.util.factory.PropertiesFactory;
import com.ctrip.framework.apollo.util.http.HttpUtil;

import com.ctrip.framework.apollo.util.yaml.YamlParser;
Expand Down Expand Up @@ -62,6 +64,7 @@ protected void configure() {
bind(ConfigServiceLocator.class).in(Singleton.class);
bind(RemoteConfigLongPollService.class).in(Singleton.class);
bind(YamlParser.class).in(Singleton.class);
bind(PropertiesFactory.class).to(DefaultPropertiesFactory.class).in(Singleton.class);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public Properties getConfig() {
if (m_fileProperties == null) {
sync();
}
Properties result = new Properties();
Properties result = propertiesFactory.getPropertiesInstance();
result.putAll(m_fileProperties);
return result;
}
Expand Down Expand Up @@ -117,7 +117,7 @@ public void onRepositoryChange(String namespace, Properties newProperties) {
if (newProperties.equals(m_fileProperties)) {
return;
}
Properties newFileProperties = new Properties();
Properties newFileProperties = propertiesFactory.getPropertiesInstance();
newFileProperties.putAll(newProperties);
updateFileProperties(newFileProperties, m_upstream.getSourceType());
this.fireRepositoryChange(namespace, newProperties);
Expand Down Expand Up @@ -191,8 +191,7 @@ private Properties loadFromLocalCacheFile(File baseDir, String namespace) throws

try {
in = new FileInputStream(file);

properties = new Properties();
properties = propertiesFactory.getPropertiesInstance();
properties.load(in);
logger.debug("Loading local config file {} successfully!", file.getAbsolutePath());
} catch (IOException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ protected synchronized void sync() {
}

private Properties transformApolloConfigToProperties(ApolloConfig apolloConfig) {
Properties result = new Properties();
Properties result = propertiesFactory.getPropertiesInstance();
result.putAll(apolloConfig.getConfigurations());
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
if (newProperties.equals(m_configProperties)) {
return;
}
Properties newConfigProperties = new Properties();
Properties newConfigProperties = propertiesFactory.getPropertiesInstance();
newConfigProperties.putAll(newProperties);

List<ConfigChange> changes = calcPropertyChanges(namespace, m_configProperties, newConfigProperties);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private synchronized void transformToProperties() {

private Properties toProperties() {
if (!this.hasContent()) {
return new Properties();
return propertiesFactory.getPropertiesInstance();
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory;
import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;
import com.ctrip.framework.apollo.spring.util.SpringInjector;
import com.ctrip.framework.apollo.util.factory.PropertiesFactory;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import java.util.List;
Expand Down Expand Up @@ -61,7 +62,7 @@ public class ApolloApplicationContextInitializer implements
private static final Logger logger = LoggerFactory.getLogger(ApolloApplicationContextInitializer.class);
private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults();
private static final String[] APOLLO_SYSTEM_PROPERTIES = {"app.id", ConfigConsts.APOLLO_CLUSTER_KEY,
"apollo.cacheDir", "apollo.accesskey.secret", ConfigConsts.APOLLO_META_KEY};
"apollo.cacheDir", "apollo.accesskey.secret", ConfigConsts.APOLLO_META_KEY, PropertiesFactory.APOLLO_PROPERTY_ORDER_ENABLE};

private final ConfigPropertySourceFactory configPropertySourceFactory = SpringInjector
.getInstance(ConfigPropertySourceFactory.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.ctrip.framework.apollo.util;

import static com.ctrip.framework.apollo.util.factory.PropertiesFactory.APOLLO_PROPERTY_ORDER_ENABLE;

import com.google.common.util.concurrent.RateLimiter;
import java.io.File;
import java.util.concurrent.TimeUnit;
Expand All @@ -18,6 +20,7 @@
* @author Jason Song([email protected])
*/
public class ConfigUtil {

private static final Logger logger = LoggerFactory.getLogger(ConfigUtil.class);
private int refreshInterval = 5;
private TimeUnit refreshIntervalTimeUnit = TimeUnit.MINUTES;
Expand All @@ -36,6 +39,7 @@ public class ConfigUtil {
private long longPollingInitialDelayInMills = 2000;//2 seconds
private boolean autoUpdateInjectedSpringProperties = true;
private final RateLimiter warnLogRateLimiter;
private boolean propertiesOrdered = false;

public ConfigUtil() {
warnLogRateLimiter = RateLimiter.create(0.017); // 1 warning log output per minute
Expand All @@ -47,6 +51,7 @@ public ConfigUtil() {
initMaxConfigCacheSize();
initLongPollingInitialDelayInMills();
initAutoUpdateInjectedSpringProperties();
initPropertiesOrdered();
}

/**
Expand Down Expand Up @@ -281,12 +286,14 @@ public TimeUnit getConfigCacheExpireTimeUnit() {
}

private void initLongPollingInitialDelayInMills() {
String customizedLongPollingInitialDelay = System.getProperty("apollo.longPollingInitialDelayInMills");
String customizedLongPollingInitialDelay = System
.getProperty("apollo.longPollingInitialDelayInMills");
if (!Strings.isNullOrEmpty(customizedLongPollingInitialDelay)) {
try {
longPollingInitialDelayInMills = Long.parseLong(customizedLongPollingInitialDelay);
} catch (Throwable ex) {
logger.error("Config for apollo.longPollingInitialDelayInMills is invalid: {}", customizedLongPollingInitialDelay);
logger.error("Config for apollo.longPollingInitialDelayInMills is invalid: {}",
customizedLongPollingInitialDelay);
}
}
}
Expand All @@ -300,7 +307,8 @@ private void initAutoUpdateInjectedSpringProperties() {
String enableAutoUpdate = System.getProperty("apollo.autoUpdateInjectedSpringProperties");
if (Strings.isNullOrEmpty(enableAutoUpdate)) {
// 2. Get from app.properties
enableAutoUpdate = Foundation.app().getProperty("apollo.autoUpdateInjectedSpringProperties", null);
enableAutoUpdate = Foundation.app()
.getProperty("apollo.autoUpdateInjectedSpringProperties", null);
}
if (!Strings.isNullOrEmpty(enableAutoUpdate)) {
autoUpdateInjectedSpringProperties = Boolean.parseBoolean(enableAutoUpdate.trim());
Expand All @@ -310,4 +318,25 @@ private void initAutoUpdateInjectedSpringProperties() {
public boolean isAutoUpdateInjectedSpringPropertiesEnabled() {
return autoUpdateInjectedSpringProperties;
}

private void initPropertiesOrdered() {
String enablePropertiesOrdered = System.getProperty(APOLLO_PROPERTY_ORDER_ENABLE);

if (Strings.isNullOrEmpty(enablePropertiesOrdered)) {
enablePropertiesOrdered = Foundation.app().getProperty(APOLLO_PROPERTY_ORDER_ENABLE, "false");
}

if (!Strings.isNullOrEmpty(enablePropertiesOrdered)) {
try {
propertiesOrdered = Boolean.parseBoolean(enablePropertiesOrdered);
} catch (Throwable ex) {
logger.warn("Config for {} is invalid: {}, set default value: false",
APOLLO_PROPERTY_ORDER_ENABLE, enablePropertiesOrdered);
}
}
}

public boolean isPropertiesOrderEnabled() {
return propertiesOrdered;
}
}
Loading

0 comments on commit 82790e5

Please sign in to comment.