未验证 提交 53566908 编写于 作者: E elandau 提交者: GitHub

Merge pull request #420 from elandau/bugfix/overrides

config: Simplify how overrides are applied
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
*/ */
package com.netflix.client.config; package com.netflix.client.config;
import com.netflix.config.ConfigurationManager;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -302,7 +301,6 @@ public class DefaultClientConfigImpl extends AbstractDefaultClientConfigImpl { ...@@ -302,7 +301,6 @@ public class DefaultClientConfigImpl extends AbstractDefaultClientConfigImpl {
} }
public void loadDefaultValues() { public void loadDefaultValues() {
super.loadDefaultValues();
set(CommonClientConfigKey.MaxHttpConnectionsPerHost, getDefaultMaxHttpConnectionsPerHost()); set(CommonClientConfigKey.MaxHttpConnectionsPerHost, getDefaultMaxHttpConnectionsPerHost());
set(CommonClientConfigKey.MaxTotalHttpConnections, getDefaultMaxTotalHttpConnections()); set(CommonClientConfigKey.MaxTotalHttpConnections, getDefaultMaxTotalHttpConnections());
set(CommonClientConfigKey.EnableConnectionPool, getDefaultEnableConnectionPool()); set(CommonClientConfigKey.EnableConnectionPool, getDefaultEnableConnectionPool());
...@@ -319,18 +317,8 @@ public class DefaultClientConfigImpl extends AbstractDefaultClientConfigImpl { ...@@ -319,18 +317,8 @@ public class DefaultClientConfigImpl extends AbstractDefaultClientConfigImpl {
set(CommonClientConfigKey.ConnIdleEvictTimeMilliSeconds, getDefaultConnectionidleTimeInMsecs()); set(CommonClientConfigKey.ConnIdleEvictTimeMilliSeconds, getDefaultConnectionidleTimeInMsecs());
set(CommonClientConfigKey.ConnectionCleanerRepeatInterval, getDefaultConnectionIdleTimertaskRepeatInMsecs()); set(CommonClientConfigKey.ConnectionCleanerRepeatInterval, getDefaultConnectionIdleTimertaskRepeatInMsecs());
set(CommonClientConfigKey.EnableGZIPContentEncodingFilter, getDefaultEnableGzipContentEncodingFilter()); set(CommonClientConfigKey.EnableGZIPContentEncodingFilter, getDefaultEnableGzipContentEncodingFilter());
String proxyHost = ConfigurationManager.getConfigInstance().getString(getDefaultPropName(CommonClientConfigKey.ProxyHost.key())); set(CommonClientConfigKey.ProxyHost, null);
if (proxyHost != null && proxyHost.length() > 0) { set(CommonClientConfigKey.ProxyPort, null);
set(CommonClientConfigKey.ProxyHost, proxyHost);
}
Integer proxyPort = ConfigurationManager
.getConfigInstance()
.getInteger(
getDefaultPropName(CommonClientConfigKey.ProxyPort),
(Integer.MIN_VALUE + 1)); // + 1 just to avoid potential clash with user setting
if (proxyPort != (Integer.MIN_VALUE + 1)) {
set(CommonClientConfigKey.ProxyPort, proxyPort);
}
set(CommonClientConfigKey.Port, getDefaultPort()); set(CommonClientConfigKey.Port, getDefaultPort());
set(CommonClientConfigKey.EnablePrimeConnections, getDefaultEnablePrimeConnections()); set(CommonClientConfigKey.EnablePrimeConnections, getDefaultEnablePrimeConnections());
set(CommonClientConfigKey.MaxRetriesPerServerPrimeConnection, getDefaultMaxRetriesPerServerPrimeConnection()); set(CommonClientConfigKey.MaxRetriesPerServerPrimeConnection, getDefaultMaxRetriesPerServerPrimeConnection());
......
...@@ -24,6 +24,7 @@ import java.lang.reflect.Modifier; ...@@ -24,6 +24,7 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -285,4 +286,16 @@ public abstract class CommonClientConfigKey<T> implements IClientConfigKey<T> { ...@@ -285,4 +286,16 @@ public abstract class CommonClientConfigKey<T> implements IClientConfigKey<T> {
@Override @Override
public T defaultValue() { return defaultValue; } public T defaultValue() { return defaultValue; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CommonClientConfigKey<?> that = (CommonClientConfigKey<?>) o;
return Objects.equals(configKey, that.configKey);
}
@Override
public int hashCode() {
return Objects.hash(configKey);
}
} }
...@@ -49,14 +49,6 @@ public interface IClientConfig { ...@@ -49,14 +49,6 @@ public interface IClientConfig {
Map<String, Object> getProperties(); Map<String, Object> getProperties();
/**
* Iterate all properties and report the default value only to the consumer
* @param consumer
*/
default void forEachDefault(BiConsumer<IClientConfigKey<?>, Object> consumer) {
throw new UnsupportedOperationException();
}
/** /**
* Iterate all properties and report the final value. Can be null if a default value is not specified. * Iterate all properties and report the final value. Can be null if a default value is not specified.
* @param consumer * @param consumer
......
...@@ -39,7 +39,7 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -39,7 +39,7 @@ public abstract class ReloadableClientConfig implements IClientConfig {
private static final String DEFAULT_NAMESPACE = "ribbon"; private static final String DEFAULT_NAMESPACE = "ribbon";
// Map of raw property names (without namespace or client) to values set via code // Map of raw property names (without namespace or client) to values set via code
private final Map<String, Object> internalProperties = new HashMap<>(); private final Map<IClientConfigKey, Object> internalProperties = new HashMap<>();
// Map of all seen dynamic properties. This map will hold on properties requested with the exception of // Map of all seen dynamic properties. This map will hold on properties requested with the exception of
// those returned from getGlobalProperty(). // those returned from getGlobalProperty().
...@@ -57,19 +57,15 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -57,19 +57,15 @@ public abstract class ReloadableClientConfig implements IClientConfig {
private String namespace = DEFAULT_NAMESPACE; private String namespace = DEFAULT_NAMESPACE;
private boolean isDynamic;
private boolean isLoaded = false; private boolean isLoaded = false;
protected ReloadableClientConfig(PropertyResolver resolver) { protected ReloadableClientConfig(PropertyResolver resolver) {
this.clientName = DEFAULT_CLIENT_NAME; this.clientName = DEFAULT_CLIENT_NAME;
this.isDynamic = false;
this.resolver = resolver; this.resolver = resolver;
} }
protected ReloadableClientConfig(PropertyResolver resolver, String clientName) { protected ReloadableClientConfig(PropertyResolver resolver, String clientName) {
this.clientName = clientName; this.clientName = clientName;
this.isDynamic = true;
this.resolver = resolver; this.resolver = resolver;
} }
...@@ -112,29 +108,24 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -112,29 +108,24 @@ public abstract class ReloadableClientConfig implements IClientConfig {
public void loadProperties(String clientName) { public void loadProperties(String clientName) {
Preconditions.checkState(isLoaded == false, "Config '{}' can only be loaded once", clientName); Preconditions.checkState(isLoaded == false, "Config '{}' can only be loaded once", clientName);
if (!isLoaded) { if (!isLoaded) {
loadDefaultValues();
this.isLoaded = true; this.isLoaded = true;
resolver.onChange(this::reload); resolver.onChange(this::reload);
} }
this.isDynamic = true;
this.clientName = clientName; this.clientName = clientName;
loadDefaultValues();
}
@Override
public void loadDefaultValues() {
this.isDynamic = true;
reload();
} }
@Override @Override
public final Map<String, Object> getProperties() { public final Map<String, Object> getProperties() {
return Collections.unmodifiableMap(internalProperties); final Map<String, Object> result = new HashMap<>(dynamicProperties.size());
} dynamicProperties.forEach((key, value) -> {
Object v = value.get().orElse(null);
@Override if (v != null) {
public void forEachDefault(BiConsumer<IClientConfigKey<?>, Object> consumer) { result.put(key.key(), String.valueOf(v));
dynamicProperties.forEach((key, value) -> consumer.accept(key, internalProperties.get(key.key()))); }
});
return result;
} }
@Override @Override
...@@ -150,9 +141,7 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -150,9 +141,7 @@ public abstract class ReloadableClientConfig implements IClientConfig {
{ {
refresh(); refresh();
if (isDynamic) { changeActions.add(this::refresh);
changeActions.add(this::refresh);
}
} }
@Override @Override
...@@ -192,11 +181,7 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -192,11 +181,7 @@ public abstract class ReloadableClientConfig implements IClientConfig {
@Override @Override
public final <T> T get(IClientConfigKey<T> key) { public final <T> T get(IClientConfigKey<T> key) {
if (isLoaded) { return getOrCreateProperty(key).get().orElse(null);
return getOrCreateProperty(key).get().orElse(null);
} else {
return getIfSet(key).orElse(null);
}
} }
private final <T> ReloadableProperty<T> getOrCreateProperty(IClientConfigKey<T> key) { private final <T> ReloadableProperty<T> getOrCreateProperty(IClientConfigKey<T> key) {
...@@ -251,6 +236,12 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -251,6 +236,12 @@ public abstract class ReloadableClientConfig implements IClientConfig {
return getIfSet(key); return getIfSet(key);
} }
/**
* Resolve a p
* @param key
* @param <T>
* @return
*/
private <T> Optional<T> resolverScopedProperty(IClientConfigKey<T> key) { private <T> Optional<T> resolverScopedProperty(IClientConfigKey<T> key) {
Optional<T> value = resolver.get(clientName + "." + getNameSpace() + "." + key.key(), key.type()); Optional<T> value = resolver.get(clientName + "." + getNameSpace() + "." + key.key(), key.type());
if (value.isPresent()) { if (value.isPresent()) {
...@@ -262,7 +253,7 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -262,7 +253,7 @@ public abstract class ReloadableClientConfig implements IClientConfig {
@Override @Override
public <T> Optional<T> getIfSet(IClientConfigKey<T> key) { public <T> Optional<T> getIfSet(IClientConfigKey<T> key) {
return Optional.ofNullable(internalProperties.get(key.key())) return Optional.ofNullable(internalProperties.get(key))
.map(value -> { .map(value -> {
final Class<T> type = key.type(); final Class<T> type = key.type();
// Unfortunately there's some legacy code setting string values for typed keys. Here are do our best to parse // Unfortunately there's some legacy code setting string values for typed keys. Here are do our best to parse
...@@ -359,7 +350,7 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -359,7 +350,7 @@ public abstract class ReloadableClientConfig implements IClientConfig {
if (value == null) { if (value == null) {
internalProperties.remove(key.key()); internalProperties.remove(key.key());
} else { } else {
internalProperties.put(key.key(), value); internalProperties.put(key, value);
} }
if (isLoaded) { if (isLoaded) {
...@@ -418,8 +409,16 @@ public abstract class ReloadableClientConfig implements IClientConfig { ...@@ -418,8 +409,16 @@ public abstract class ReloadableClientConfig implements IClientConfig {
return this; return this;
} }
this.internalProperties.putAll(override.getProperties()); // When overriding we only really care of picking up properties that were explicitly set in code. This is a
reload(); // bit of an optimization to avoid excessive memory allocation as requests are made and overrides are applied
if (override instanceof ReloadableClientConfig) {
((ReloadableClientConfig)override).internalProperties.forEach((key, value) -> {
if (value != null) {
setProperty(key, value);
}
});
}
return this; return this;
} }
......
...@@ -30,6 +30,8 @@ import org.junit.Rule; ...@@ -30,6 +30,8 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TestName; import org.junit.rules.TestName;
import org.junit.runners.MethodSorters; import org.junit.runners.MethodSorters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Properties; import java.util.Properties;
...@@ -41,6 +43,8 @@ import java.util.Properties; ...@@ -41,6 +43,8 @@ import java.util.Properties;
*/ */
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ClientConfigTest { public class ClientConfigTest {
private static final Logger LOG = LoggerFactory.getLogger(ClientConfigTest.class);
@Rule @Rule
public TestName testName = new TestName(); public TestName testName = new TestName();
...@@ -186,7 +190,7 @@ public class ClientConfigTest { ...@@ -186,7 +190,7 @@ public class ClientConfigTest {
ConfigurationManager.getConfigInstance().setProperty("testValueOf.ribbon.CustomValueOf", "value"); ConfigurationManager.getConfigInstance().setProperty("testValueOf.ribbon.CustomValueOf", "value");
DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl(); DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl();
clientConfig.setClientName("testValueOf"); clientConfig.loadProperties("testValueOf");
Property<CustomValueOf> prop = clientConfig.getDynamicProperty(CUSTOM_KEY); Property<CustomValueOf> prop = clientConfig.getDynamicProperty(CUSTOM_KEY);
Assert.assertEquals("value", prop.getOrDefault().getValue()); Assert.assertEquals("value", prop.getOrDefault().getValue());
...@@ -198,7 +202,7 @@ public class ClientConfigTest { ...@@ -198,7 +202,7 @@ public class ClientConfigTest {
ConfigurationManager.getConfigInstance().setProperty("testScopedProperty.ribbon.foo.ScopePropertyTimeout", "1000"); ConfigurationManager.getConfigInstance().setProperty("testScopedProperty.ribbon.foo.ScopePropertyTimeout", "1000");
DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl(); DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl();
clientConfig.setClientName("testScopedProperty"); clientConfig.loadProperties("testScopedProperty");
Property<Integer> prop = clientConfig.getScopedProperty(new CommonClientConfigKey<Integer>("foo.ScopePropertyTimeout", 0) {}); Property<Integer> prop = clientConfig.getScopedProperty(new CommonClientConfigKey<Integer>("foo.ScopePropertyTimeout", 0) {});
Assert.assertEquals(1000, prop.get().get().intValue()); Assert.assertEquals(1000, prop.get().get().intValue());
......
...@@ -84,7 +84,7 @@ public class SubsetFilterTest { ...@@ -84,7 +84,7 @@ public class SubsetFilterTest {
@Test @Test
public void testFiltering() { public void testFiltering() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl(); DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.setClientName("SubsetFilerTest"); config.loadProperties("SubsetFilerTest");
ServerListSubsetFilter<Server> filter = new ServerListSubsetFilter<Server>(config); ServerListSubsetFilter<Server> filter = new ServerListSubsetFilter<Server>(config);
LoadBalancerStats stats = new LoadBalancerStats("default"); LoadBalancerStats stats = new LoadBalancerStats("default");
......
...@@ -74,7 +74,7 @@ public class ZoneAwareLoadBalancerTest { ...@@ -74,7 +74,7 @@ public class ZoneAwareLoadBalancerTest {
ConfigurationManager.getConfigInstance().setProperty("niws.loadbalancer.serverStats.activeRequestsCount.effectiveWindowSeconds", 10); ConfigurationManager.getConfigInstance().setProperty("niws.loadbalancer.serverStats.activeRequestsCount.effectiveWindowSeconds", 10);
DefaultClientConfigImpl config = new DefaultClientConfigImpl(); DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.setClientName("testChooseZone"); config.loadProperties("testChooseZone");
ZoneAwareLoadBalancer<Server> balancer = new ZoneAwareLoadBalancer<Server>(); ZoneAwareLoadBalancer<Server> balancer = new ZoneAwareLoadBalancer<Server>();
balancer.init(); balancer.init();
IRule globalRule = new RoundRobinRule(); IRule globalRule = new RoundRobinRule();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册