diff --git a/build.gradle b/build.gradle index 8bd5db77b23a8eeb3d0108a791a8096f90fecc3d..51904f58dd66e679c9279ae9f15caf1725918c30 100644 --- a/build.gradle +++ b/build.gradle @@ -72,8 +72,8 @@ project(':ribbon-transport') { compile project(':ribbon-core') compile project(':ribbon-loadbalancer') compile project(':ribbon-core') - compile 'com.netflix.rxnetty:rx-netty:0.3.5' - compile 'com.netflix.rxnetty:rx-netty-contexts:0.3.5' + compile 'com.netflix.rxnetty:rx-netty:0.3.6' + compile 'com.netflix.rxnetty:rx-netty-contexts:0.3.6' testCompile 'com.google.mockwebserver:mockwebserver:20130706' testCompile project(':ribbon-test') } @@ -141,6 +141,7 @@ project(':ribbon-client-extensions') { compile 'com.netflix.hystrix:hystrix-core:1.4.0-RC4' compile 'com.netflix.evcache:evcache-client:1.0.5' compile project(':ribbon-transport') + compile project(':ribbon-eureka') testCompile 'com.google.mockwebserver:mockwebserver:20130706' } diff --git a/ribbon-client-extensions/src/examples/java/com/netflix/ribbonclientextensions/RibbonExamples.java b/ribbon-client-extensions/src/examples/java/com/netflix/ribbonclientextensions/RibbonExamples.java index 6d25f9ef1bf536abb0dc85acaf3eca09ce1e6fc2..4eeb10774404e1eccea8c2113bd5ff725fd2036d 100644 --- a/ribbon-client-extensions/src/examples/java/com/netflix/ribbonclientextensions/RibbonExamples.java +++ b/ribbon-client-extensions/src/examples/java/com/netflix/ribbonclientextensions/RibbonExamples.java @@ -20,7 +20,7 @@ import com.netflix.ribbonclientextensions.hystrix.FallbackHandler; public class RibbonExamples { public static void main(String[] args) { HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient"); - HttpRequestTemplate template = group.requestTemplateBuilder().newRequestTemplate("GetUser") + HttpRequestTemplate template = group.newRequestTemplate("GetUser") .withResponseValidator(new ResponseValidator>() { @Override diff --git a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/ClientOptions.java b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/ClientOptions.java new file mode 100644 index 0000000000000000000000000000000000000000..ed5a48039fe7da4e7f03b649b5e5bbebbda48807 --- /dev/null +++ b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/ClientOptions.java @@ -0,0 +1,89 @@ +package com.netflix.ribbonclientextensions; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.netflix.client.config.CommonClientConfigKey; +import com.netflix.client.config.IClientConfigKey; +import com.netflix.loadbalancer.Server; +import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList; + +public final class ClientOptions { + + private Map, Object> options; + + private ClientOptions() { + options = new ConcurrentHashMap, Object>(); + } + + public static ClientOptions create() { + return new ClientOptions(); + } + + public ClientOptions useEurekaDynamicServerList(String vipAddress) { + options.put(IClientConfigKey.CommonKeys.NIWSServerListClassName, DiscoveryEnabledNIWSServerList.class.getName()); + options.put(IClientConfigKey.CommonKeys.DeploymentContextBasedVipAddresses, vipAddress); + return this; + } + + public ClientOptions useConfigurationBasedServerList(String serverList) { + options.put(IClientConfigKey.CommonKeys.ListOfServers, serverList); + return this; + } + + public ClientOptions withMaxAutoRetries(int value) { + options.put(IClientConfigKey.CommonKeys.MaxAutoRetries, value); + return this; + } + + public ClientOptions withMaxAutoRetriesNextServer(int value) { + options.put(IClientConfigKey.CommonKeys.MaxAutoRetriesNextServer, value); + return this; + } + + public ClientOptions withRetryOnAllOperations(boolean value) { + options.put(IClientConfigKey.CommonKeys.OkToRetryOnAllOperations, value); + return this; + } + + public ClientOptions withMaxConnectionsPerHost(int value) { + options.put(IClientConfigKey.CommonKeys.MaxConnectionsPerHost, value); + return this; + } + + public ClientOptions withMaxTotalConnections(int value) { + options.put(IClientConfigKey.CommonKeys.MaxTotalConnections, value); + return this; + } + + public ClientOptions withConnectTimeout(int value) { + options.put(IClientConfigKey.CommonKeys.ConnectTimeout, value); + return this; + } + + public ClientOptions withReadTimeout(int value) { + options.put(IClientConfigKey.CommonKeys.ReadTimeout, value); + return this; + } + + public ClientOptions withFollowRedirects(boolean value) { + options.put(IClientConfigKey.CommonKeys.FollowRedirects, value); + return this; + } + + public ClientOptions withConnectionPoolIdleEvictTimeMilliseconds(int value) { + options.put(IClientConfigKey.CommonKeys.ConnIdleEvictTimeMilliSeconds, value); + return this; + } + + public ClientOptions withLoadBalancerEnabled(boolean value) { + options.put(IClientConfigKey.CommonKeys.InitializeNFLoadBalancer, value); + return this; + } + + Map, Object> getOptions() { + return options; + } + +} diff --git a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/RequestTemplate.java b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/RequestTemplate.java index 4ebdf848f054e8f5db417d0f59304f36e6724c41..3d78b299447fcf2d301c3f066dc017c33db05e28 100644 --- a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/RequestTemplate.java +++ b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/RequestTemplate.java @@ -6,8 +6,7 @@ import com.netflix.ribbonclientextensions.hystrix.FallbackHandler; /** * @author awang * - * @param request input entity type - * @param response entity type + * @param response entity type * @param response meta data, e.g. HttpClientResponse */ public interface RequestTemplate { diff --git a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/ResourceGroup.java b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/ResourceGroup.java index a77e35f75cd0c175913087ccf1f4ae590405f32e..3eaeea9237f795a29b5cdc9b7f7b62fde729951f 100644 --- a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/ResourceGroup.java +++ b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/ResourceGroup.java @@ -1,18 +1,39 @@ package com.netflix.ribbonclientextensions; import com.netflix.client.config.IClientConfig; -import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.client.config.IClientConfigKey; -public interface ResourceGroup { - String name(); +public abstract class ResourceGroup> { + private String name; + private IClientConfig clientConfig; - ResourceGroup withLoadBalancer(ILoadBalancer loadBalancer); + public ResourceGroup(String name) { + this(name, null); + } + + public ResourceGroup(String name, ClientOptions options) { + this.name = name; + clientConfig = loadDefaultConfig(name); + if (options != null) { + for (IClientConfigKey key: options.getOptions().keySet()) { + clientConfig.setPropertyWithType(key, options.getOptions().get(key)); + } + } + } - ResourceGroup withClientConfig(IClientConfig config); + ResourceGroup(IClientConfig clientConfig) { + this.clientConfig = clientConfig; + } - > RequestTemplateBuilder requestTemplateBuilder(); + protected abstract IClientConfig loadDefaultConfig(String name); - public abstract class RequestTemplateBuilder> { - public abstract T newRequestTemplate(String name, Class classType); + protected final IClientConfig getClientConfig() { + return clientConfig; } + + public String name() { + return name; + } + + public abstract T newRequestTemplate(String name, Class classType); } diff --git a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/Ribbon.java b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/Ribbon.java index b178d980efba25f862f2a3aeb34379bf65cb8c55..90ff2cb2c24757986f91cc204b224057274c8e01 100644 --- a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/Ribbon.java +++ b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/Ribbon.java @@ -2,8 +2,6 @@ package com.netflix.ribbonclientextensions; import com.netflix.ribbonclientextensions.http.HttpResourceGroup; -import io.reactivex.netty.protocol.http.client.HttpClient; - public final class Ribbon { private Ribbon() { @@ -12,8 +10,12 @@ public final class Ribbon { public static HttpResourceGroup createHttpResourceGroup(String name) { return new HttpResourceGroup(name); } - - public static T from(Class contract, HttpClient transportClient) { + + public static HttpResourceGroup createHttpResourceGroup(String name, ClientOptions options) { + return new HttpResourceGroup(name, options); + } + + public static T from(Class contract) { return null; } } diff --git a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/http/HttpResourceGroup.java b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/http/HttpResourceGroup.java index 3ba023e15a958cea6a743b5d9f8e1f128b5215a9..95b12831f5ac6368ac96ae8c8a82909d2da2d8bc 100644 --- a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/http/HttpResourceGroup.java +++ b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/http/HttpResourceGroup.java @@ -10,76 +10,38 @@ import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfigKey; import com.netflix.client.netty.RibbonTransport; import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.ribbonclientextensions.ClientOptions; +import com.netflix.ribbonclientextensions.RequestTemplate; import com.netflix.ribbonclientextensions.ResourceGroup; -public class HttpResourceGroup implements ResourceGroup { - - private String groupName; - private IClientConfig config; - private ILoadBalancer loadBalancer; - - public class HttpRequestTemplateBuilder extends RequestTemplateBuilder>{ - private HttpClient client; - HttpRequestTemplateBuilder() { - if (loadBalancer == null) { - client = RibbonTransport.newHttpClient(config); - } else { - client = RibbonTransport.newHttpClient(loadBalancer, config); - } - } - @Override - public HttpRequestTemplate newRequestTemplate(String name, Class type) { - return new HttpRequestTemplate(name, HttpResourceGroup.this, client, type); - } - - public HttpRequestTemplate newRequestTemplate(String name) { - return newRequestTemplate(name, ByteBuf.class); - } - - } +public class HttpResourceGroup extends ResourceGroup> { + private final HttpClient client; - @Override - public String name() { - return groupName; + public HttpResourceGroup(String groupName) { + this(groupName, null); } - public HttpResourceGroup(String groupName) { - this.groupName = groupName; - config = getDefaultConfig(groupName); + public HttpResourceGroup(String groupName, ClientOptions options) { + super(groupName, options); + client = RibbonTransport.newHttpClient(getClientConfig()); } - protected IClientConfig getDefaultConfig(String groupName) { + protected IClientConfig loadDefaultConfig(String groupName) { return ClientConfigBuilder.newBuilderWithArchaiusProperties(groupName).build(); } public HttpResourceGroup withCommonHeader(String name, String value) { return this; } - - @SuppressWarnings({"rawtypes", "unchecked"}) + @Override - public HttpResourceGroup withClientConfig(IClientConfig overrideConfig) { - if (config instanceof DefaultClientConfigImpl) { - ((DefaultClientConfigImpl) config).applyOverride(overrideConfig); - } else { - for (IClientConfigKey key: CommonClientConfigKey.keys()) { - Object value = overrideConfig.getPropertyWithType(key); - if (value != null) { - config.setPropertyWithType(key, value); - } - } - } - return this; + public HttpRequestTemplate newRequestTemplate(String name, + Class classType) { + return new HttpRequestTemplate(name, HttpResourceGroup.this, client, classType); } - public HttpResourceGroup withLoadBalancer(ILoadBalancer loadBalancer) { - this.loadBalancer = loadBalancer; - return this; + public HttpRequestTemplate newRequestTemplate(String name) { + return newRequestTemplate(name, ByteBuf.class); } - @SuppressWarnings("unchecked") - @Override - public HttpRequestTemplateBuilder requestTemplateBuilder() { - return new HttpRequestTemplateBuilder(); - } } diff --git a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/hystrix/FallbackHandler.java b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/hystrix/FallbackHandler.java index f6b826604325de113b4da82b8f7ead136ab8c7ca..c62eef06442b0796dc842b2eae57478b0248f405 100644 --- a/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/hystrix/FallbackHandler.java +++ b/ribbon-client-extensions/src/main/java/com/netflix/ribbonclientextensions/hystrix/FallbackHandler.java @@ -11,7 +11,6 @@ import rx.Observable; * @author awang * * @param Output entity type - * @param Response */ public interface FallbackHandler { public Observable getFallback(HystrixExecutableInfo hystrixInfo, Map requestProperties); diff --git a/ribbon-client-extensions/src/test/java/com/netflix/ribbonclientextensions/RibbonTest.java b/ribbon-client-extensions/src/test/java/com/netflix/ribbonclientextensions/RibbonTest.java index 4295deb0591da74ae58967e33955d8446b4d0a2a..9ed1e2b06cfcd748656596d3c44768b6f1f5f53f 100644 --- a/ribbon-client-extensions/src/test/java/com/netflix/ribbonclientextensions/RibbonTest.java +++ b/ribbon-client-extensions/src/test/java/com/netflix/ribbonclientextensions/RibbonTest.java @@ -1,21 +1,19 @@ package com.netflix.ribbonclientextensions; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.reactivex.netty.protocol.http.client.HttpClientResponse; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.reactivex.netty.protocol.http.client.HttpClient; -import io.reactivex.netty.protocol.http.client.HttpClientResponse; - -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; import org.junit.Test; import rx.Observable; @@ -26,10 +24,6 @@ import rx.functions.Func1; import com.google.common.collect.Lists; import com.google.mockwebserver.MockResponse; import com.google.mockwebserver.MockWebServer; -import com.netflix.client.config.CommonClientConfigKey; -import com.netflix.client.config.DefaultClientConfigImpl; -import com.netflix.client.config.IClientConfigKey; -import com.netflix.client.netty.RibbonTransport; import com.netflix.hystrix.HystrixCommandGroupKey; import com.netflix.hystrix.HystrixCommandProperties; import com.netflix.hystrix.HystrixExecutableInfo; @@ -53,15 +47,11 @@ public class RibbonTest { .setBody(content)); server.play(); - ILoadBalancer lb = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(Lists.newArrayList( - new Server("localhost", 12345), - new Server("localhost", 10092), - new Server("localhost", server.getPort()))); - // HttpClient httpClient = RibbonTransport.newHttpClient(lb, DefaultClientConfigImpl.getClientConfigWithDefaultValues().setPropertyWithType(CommonClientConfigKey.MaxAutoRetriesNextServer, 3)); - HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient"); - group.withLoadBalancer(lb) - .withClientConfig(DefaultClientConfigImpl.getEmptyConfig().setPropertyWithType(CommonClientConfigKey.MaxAutoRetriesNextServer, 3)); - HttpRequestTemplate template = group.requestTemplateBuilder().newRequestTemplate("test", ByteBuf.class); + HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient", + ClientOptions.create() + .withMaxAutoRetriesNextServer(3) + .useConfigurationBasedServerList("localhost:12345, localhost:10092, localhost:" + server.getPort())); + HttpRequestTemplate template = group.newRequestTemplate("test", ByteBuf.class); RibbonRequest request = template.withUri("/").requestBuilder().build(); String result = request.execute().toString(Charset.defaultCharset()); assertEquals(content, result); @@ -77,14 +67,11 @@ public class RibbonTest { .setBody(content)); server.play(); - ILoadBalancer lb = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(Lists.newArrayList(new Server("localhost", server.getPort()))); - HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient"); - group.withLoadBalancer(lb) - .withClientConfig(DefaultClientConfigImpl.getEmptyConfig().setPropertyWithType(CommonClientConfigKey.MaxAutoRetriesNextServer, 3)); + HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient", ClientOptions.create() + .useConfigurationBasedServerList("localhost:" + server.getPort()) + .withMaxAutoRetriesNextServer(3)); - HttpRequestTemplate template = group.withLoadBalancer(lb) - .requestTemplateBuilder() - .newRequestTemplate("test", ByteBuf.class); + HttpRequestTemplate template = group.newRequestTemplate("test"); RibbonRequest request = template.withUri("/") .addCacheProvider("somekey", new CacheProvider(){ @Override @@ -124,14 +111,10 @@ public class RibbonTest { .setBody(content)); server.play(); - ILoadBalancer lb = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(Lists.newArrayList(new Server("localhost", server.getPort()))); - - HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient"); - group.withLoadBalancer(lb); + HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient", ClientOptions.create() + .useConfigurationBasedServerList("localhost:" + server.getPort())); - HttpRequestTemplate template = group.withLoadBalancer(lb) - .requestTemplateBuilder() - .newRequestTemplate("test", ByteBuf.class); + HttpRequestTemplate template = group.newRequestTemplate("test", ByteBuf.class); template.withResponseValidator(new ResponseValidator>() { @Override @@ -166,12 +149,10 @@ public class RibbonTest { @Test public void testFallback() throws IOException { - ILoadBalancer lb = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(Lists.newArrayList(new Server("localhost", 12345))); - HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient"); - group.withLoadBalancer(lb) - .withClientConfig(DefaultClientConfigImpl.getEmptyConfig().setPropertyWithType(IClientConfigKey.CommonKeys.MaxAutoRetriesNextServer, 1)); - - HttpRequestTemplate template = group.requestTemplateBuilder().newRequestTemplate("test", ByteBuf.class); + HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient", ClientOptions.create() + .useConfigurationBasedServerList("localhost:12345") + .withMaxAutoRetriesNextServer(1)); + HttpRequestTemplate template = group.newRequestTemplate("test", ByteBuf.class); final String fallback = "fallback"; RibbonRequest request = template.withUri("/") .withFallbackProvider(new FallbackHandler() { @@ -179,7 +160,11 @@ public class RibbonTest { public Observable getFallback( HystrixExecutableInfo hystrixInfo, Map requestProperties) { - return Observable.just(Unpooled.buffer().writeBytes(fallback.getBytes())); + try { + return Observable.just(Unpooled.buffer().writeBytes(fallback.getBytes("UTF-8"))); + } catch (UnsupportedEncodingException e) { + return Observable.error(e); + } } }) .requestBuilder().build(); @@ -208,11 +193,10 @@ public class RibbonTest { @Test public void testCacheHit() { - ILoadBalancer lb = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(Lists.newArrayList(new Server("localhost", 12345))); - HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient") - .withClientConfig(DefaultClientConfigImpl.getEmptyConfig().setPropertyWithType(IClientConfigKey.CommonKeys.MaxAutoRetriesNextServer, 1)); - HttpRequestTemplate template = group.withLoadBalancer(lb) - .requestTemplateBuilder().newRequestTemplate("test"); + HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient", ClientOptions.create() + .useConfigurationBasedServerList("localhost:12345") + .withMaxAutoRetriesNextServer(1)); + HttpRequestTemplate template = group.newRequestTemplate("test"); final String content = "from cache"; final String cacheKey = "somekey"; RibbonRequest request = template.addCacheProvider(cacheKey, new CacheProvider(){ @@ -225,7 +209,11 @@ public class RibbonTest { @Override public Observable get(String key, Map vars) { if (key.equals(cacheKey)) { - return Observable.just(Unpooled.buffer().writeBytes(content.getBytes())); + try { + return Observable.just(Unpooled.buffer().writeBytes(content.getBytes("UTF-8"))); + } catch (UnsupportedEncodingException e) { + return Observable.error(e); + } } else { return Observable.error(new Exception("Cache miss")); } @@ -249,11 +237,11 @@ public class RibbonTest { .setBody(content)); server.play(); - ILoadBalancer lb = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(Lists.newArrayList(new Server("localhost", server.getPort()))); - HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient") - .withClientConfig(DefaultClientConfigImpl.getEmptyConfig().setPropertyWithType(IClientConfigKey.CommonKeys.MaxAutoRetriesNextServer, 1)); - HttpRequestTemplate template = group.withLoadBalancer(lb) - .requestTemplateBuilder().newRequestTemplate("test"); + HttpResourceGroup group = Ribbon.createHttpResourceGroup("myclient", ClientOptions.create() + .useConfigurationBasedServerList("localhost:" + server.getPort()) + .withMaxAutoRetriesNextServer(1)); + + HttpRequestTemplate template = group.newRequestTemplate("test"); final String cacheKey = "somekey"; RibbonRequest request = template.addCacheProvider(cacheKey, new CacheProvider(){ @Override @@ -274,5 +262,5 @@ public class RibbonTest { .requestBuilder().build(); String result = request.execute().toString(Charset.defaultCharset()); assertEquals(content, result); - } + } } diff --git a/ribbon-client-extensions/src/test/java/com/netflix/ribbonclientextensions/http/TemplateBuilderTest.java b/ribbon-client-extensions/src/test/java/com/netflix/ribbonclientextensions/http/TemplateBuilderTest.java index 9b995299c6f5ebc83043934e311071225de02559..4fe2333cb11346fa108c413ad5e3316a2a2efd86 100644 --- a/ribbon-client-extensions/src/test/java/com/netflix/ribbonclientextensions/http/TemplateBuilderTest.java +++ b/ribbon-client-extensions/src/test/java/com/netflix/ribbonclientextensions/http/TemplateBuilderTest.java @@ -13,7 +13,7 @@ public class TemplateBuilderTest { public void testVarReplacement() { HttpResourceGroup group = Ribbon.createHttpResourceGroup("test"); - HttpRequestTemplate template = group.requestTemplateBuilder().newRequestTemplate("resource1", ByteBuf.class); + HttpRequestTemplate template = group.newRequestTemplate("resource1", ByteBuf.class); template.withUri("/foo/{id}?name={name}"); HttpClientRequest request = template .requestBuilder() diff --git a/ribbon-core/src/main/java/com/netflix/client/config/ClientConfigBuilder.java b/ribbon-core/src/main/java/com/netflix/client/config/ClientConfigBuilder.java index 7590e9767913c0dcd4f2d372b54b170db9e28eb7..4d89bd223901cea29a2611f04257842a86a8802f 100644 --- a/ribbon-core/src/main/java/com/netflix/client/config/ClientConfigBuilder.java +++ b/ribbon-core/src/main/java/com/netflix/client/config/ClientConfigBuilder.java @@ -4,7 +4,7 @@ public class ClientConfigBuilder { private IClientConfig config; - private ClientConfigBuilder() { + ClientConfigBuilder() { } public static ClientConfigBuilder newBuilder() { @@ -100,13 +100,15 @@ public class ClientConfigBuilder { return this; } - public ClientConfigBuilder withMaxHttpConnectionsPerHost(int value) { + public ClientConfigBuilder withMaxConnectionsPerHost(int value) { config.setPropertyWithType(CommonClientConfigKey.MaxHttpConnectionsPerHost, value); + config.setPropertyWithType(CommonClientConfigKey.MaxConnectionsPerHost, value); return this; } - public ClientConfigBuilder withMaxTotalHttpConnections(int value) { + public ClientConfigBuilder withMaxTotalConnections(int value) { config.setPropertyWithType(CommonClientConfigKey.MaxTotalHttpConnections, value); + config.setPropertyWithType(CommonClientConfigKey.MaxTotalConnections, value); return this; } diff --git a/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java b/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java index 625a817d670bfad365cc1121dbd051916cd8467a..9b9dac1157ae2013e7035dc38b16be156fcc6b83 100644 --- a/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java +++ b/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java @@ -182,6 +182,8 @@ public abstract class CommonClientConfigKey implements IClientConfigKey { public static final IClientConfigKey RequestIdHeaderName = new CommonClientConfigKey("RequestIdHeaderName") {}; + public static final IClientConfigKey ListOfServers = new CommonClientConfigKey("listOfServers") {}; + private static final Set keys = new HashSet(); static { diff --git a/ribbon-core/src/main/java/com/netflix/client/config/DefaultClientConfigImpl.java b/ribbon-core/src/main/java/com/netflix/client/config/DefaultClientConfigImpl.java index 1550e0f1fd98d0d1916d2afdd38b5ce41f62cfb3..cfbbf0378238585fb17359aa2a292eaa5bb7ee1d 100644 --- a/ribbon-core/src/main/java/com/netflix/client/config/DefaultClientConfigImpl.java +++ b/ribbon-core/src/main/java/com/netflix/client/config/DefaultClientConfigImpl.java @@ -23,6 +23,7 @@ import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; +import org.apache.commons.configuration.AbstractConfiguration; import org.apache.commons.configuration.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -430,6 +431,7 @@ public class DefaultClientConfigImpl implements IClientConfig { putDefaultStringProperty(CommonClientConfigKey.VipAddressResolverClassName, getDefaultVipaddressResolverClassname()); putDefaultBooleanProperty(CommonClientConfigKey.IsClientAuthRequired, getDefaultIsClientAuthRequired()); putDefaultStringProperty(CommonClientConfigKey.RequestIdHeaderName, getDefaultRequestIdHeaderName()); + putDefaultStringProperty(CommonClientConfigKey.ListOfServers, ""); } public Boolean getDefaultEnableConnectionPool() { @@ -574,9 +576,42 @@ public class DefaultClientConfigImpl implements IClientConfig { if (prop.startsWith(getNameSpace())){ prop = prop.substring(getNameSpace().length() + 1); } - setPropertyInternal(prop, props.getProperty(key)); + setPropertyInternal(prop, getStringValue(props, key)); } + } + + /** + * This is to workaround the issue that {@link AbstractConfiguration} by default + * automatically convert comma delimited string to array + */ + protected static String getStringValue(Configuration config, String key) { + try { + String values[] = config.getStringArray(key); + if (values == null) { + return null; + } + if (values.length == 0) { + return config.getString(key); + } else if (values.length == 1) { + return values[0]; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < values.length; i++) { + sb.append(values[i]); + if (i != values.length - 1) { + sb.append(","); + } + } + return sb.toString(); + } catch (Exception e) { + Object v = config.getProperty(key); + if (v != null) { + return String.valueOf(v); + } else { + return null; + } + } } @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "DC_DOUBLECHECK") diff --git a/ribbon-examples/src/main/java/com/netflix/ribbon/examples/netty/http/LoadBalancingExample.java b/ribbon-examples/src/main/java/com/netflix/ribbon/examples/netty/http/LoadBalancingExample.java index 696b50a1324623f60f1c7c53de074ec5d03c81bc..42a511e088ff3b62aed0997c5620fc655774ab90 100644 --- a/ribbon-examples/src/main/java/com/netflix/ribbon/examples/netty/http/LoadBalancingExample.java +++ b/ribbon-examples/src/main/java/com/netflix/ribbon/examples/netty/http/LoadBalancingExample.java @@ -10,6 +10,7 @@ import java.util.concurrent.CountDownLatch; import rx.Observer; import com.google.common.collect.Lists; +import com.netflix.client.netty.RibbonTransport; import com.netflix.client.netty.http.NettyHttpClient; import com.netflix.loadbalancer.BaseLoadBalancer; import com.netflix.loadbalancer.LoadBalancerBuilder; @@ -22,7 +23,7 @@ public class LoadBalancingExample { BaseLoadBalancer lb = LoadBalancerBuilder.newBuilder() .buildFixedServerListLoadBalancer(servers); - NettyHttpClient client = NettyHttpClient.createDefaultHttpClient(lb); + NettyHttpClient client = RibbonTransport.newHttpClient(lb); final CountDownLatch latch = new CountDownLatch(servers.size()); Observer> observer = new Observer>() { @Override diff --git a/ribbon-examples/src/main/java/com/netflix/ribbon/examples/netty/http/SimpleGet.java b/ribbon-examples/src/main/java/com/netflix/ribbon/examples/netty/http/SimpleGet.java index f36fcc84d18e1e2ce0ef0cdf727d5e02247d28f7..b9f571b0505b74d86327b5f8e171f85440606924 100644 --- a/ribbon-examples/src/main/java/com/netflix/ribbon/examples/netty/http/SimpleGet.java +++ b/ribbon-examples/src/main/java/com/netflix/ribbon/examples/netty/http/SimpleGet.java @@ -10,12 +10,13 @@ import java.util.concurrent.TimeUnit; import rx.functions.Action1; +import com.netflix.client.netty.RibbonTransport; import com.netflix.client.netty.http.NettyHttpClient; public class SimpleGet { @edu.umd.cs.findbugs.annotations.SuppressWarnings public static void main(String[] args) throws Exception { - NettyHttpClient client = NettyHttpClient.createDefaultHttpClient(); + NettyHttpClient client = RibbonTransport.newHttpClient(); HttpClientRequest request = HttpClientRequest.createGet("/"); final CountDownLatch latch = new CountDownLatch(1); diff --git a/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/ConfigurationBasedServerList.java b/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/ConfigurationBasedServerList.java index a79668aac2ac29ab64d8d7f7a0ba09c9cc32bbef..2aab3f39fdc8323678c7526a9b239428796a95fc 100644 --- a/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/ConfigurationBasedServerList.java +++ b/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/ConfigurationBasedServerList.java @@ -22,6 +22,8 @@ import java.util.Collections; import java.util.List; import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.DefaultClientConfigImpl; import com.netflix.client.config.IClientConfig; import com.netflix.config.DynamicPropertyFactory; @@ -40,44 +42,31 @@ import com.netflix.config.DynamicStringProperty; */ public class ConfigurationBasedServerList extends AbstractServerList { - public static final String PROP_NAME = "listOfServers"; - private String propertyName = DefaultClientConfigImpl.DEFAULT_PROPERTY_NAME_SPACE + "." + PROP_NAME; - private DynamicStringProperty dynamicProp; - private volatile List list = Collections.emptyList(); + private IClientConfig clientConfig; @Override public List getInitialListOfServers() { - return list; + return getUpdatedListOfServers(); } @Override public List getUpdatedListOfServers() { - return list; + String listOfServers = clientConfig.getPropertyWithType(CommonClientConfigKey.ListOfServers); + return derive(listOfServers); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) { - propertyName = clientConfig.getClientName() + "." + clientConfig.getNameSpace() + "." + PROP_NAME; - dynamicProp = DynamicPropertyFactory.getInstance().getStringProperty(propertyName, null); - derive(); - dynamicProp.addCallback(new Runnable() { - @Override - public void run() { - derive(); - } - }); + this.clientConfig = clientConfig; } - private void derive() { - String value = dynamicProp.get(); - if (Strings.isNullOrEmpty(value)) { - list = Collections.emptyList(); - } else { - List newList = new ArrayList(); + private List derive(String value) { + List list = Lists.newArrayList(); + if (!Strings.isNullOrEmpty(value)) { for (String s: value.split(",")) { - newList.add(new Server(s.trim())); + list.add(new Server(s.trim())); } - list = newList; } + return list; } } diff --git a/ribbon-loadbalancer/src/test/java/com/netflix/loadbalancer/ConfigurationBasedServerListTest.java b/ribbon-loadbalancer/src/test/java/com/netflix/loadbalancer/ConfigurationBasedServerListTest.java index fab05dcdb1c6f6196db53923f90218e5cea8528b..8a3f3f275d5fa5c7a41c487d13ea8f6668a82d29 100644 --- a/ribbon-loadbalancer/src/test/java/com/netflix/loadbalancer/ConfigurationBasedServerListTest.java +++ b/ribbon-loadbalancer/src/test/java/com/netflix/loadbalancer/ConfigurationBasedServerListTest.java @@ -32,8 +32,7 @@ public class ConfigurationBasedServerListTest { @Test public void testList() { ConfigurationBasedServerList list = new ConfigurationBasedServerList(); - DefaultClientConfigImpl config = new DefaultClientConfigImpl(); - config.setClientName("junit1"); + DefaultClientConfigImpl config = DefaultClientConfigImpl.getClientConfigWithDefaultValues("junit1"); list.initWithNiwsConfig(config); assertTrue(list.getInitialListOfServers().isEmpty()); ConfigurationManager.getConfigInstance().setProperty("junit1.ribbon.listOfServers", "abc.com:80,microsoft.com,1.2.3.4:8080"); diff --git a/ribbon-transport/src/main/java/com/netflix/client/netty/LoadBalancingRxClientWithPoolOptions.java b/ribbon-transport/src/main/java/com/netflix/client/netty/LoadBalancingRxClientWithPoolOptions.java index 896652fa7fd2251f3185b63633e61d0c704e76f7..56126f23c4aa2df97e3193bc516cac26425d1d90 100644 --- a/ribbon-transport/src/main/java/com/netflix/client/netty/LoadBalancingRxClientWithPoolOptions.java +++ b/ribbon-transport/src/main/java/com/netflix/client/netty/LoadBalancingRxClientWithPoolOptions.java @@ -29,7 +29,7 @@ public abstract class LoadBalancingRxClientWithPoolOptions stats; private Observable poolStateChangeEventObservable; protected ScheduledExecutorService poolCleanerScheduler; - protected boolean poolEnabled; + protected boolean poolEnabled = true; public LoadBalancingRxClientWithPoolOptions(IClientConfig config, RetryHandler retryHandler, diff --git a/ribbon-transport/src/main/java/com/netflix/client/netty/RibbonTransport.java b/ribbon-transport/src/main/java/com/netflix/client/netty/RibbonTransport.java index 30b480046148f806965399140ba1c2059e476f72..4e924893f940315f09fca393c171a304915a90fa 100644 --- a/ribbon-transport/src/main/java/com/netflix/client/netty/RibbonTransport.java +++ b/ribbon-transport/src/main/java/com/netflix/client/netty/RibbonTransport.java @@ -92,57 +92,63 @@ public final class RibbonTransport { return new LoadBalancingUdpClient(config, getDefaultRetryHandlerWithConfig(config), pipelineConfigurator); } - public static HttpClient newHttpClient() { + public static NettyHttpClient newHttpClient() { IClientConfig config = DefaultClientConfigImpl.getClientConfigWithDefaultValues(); return newHttpClient(config); } - public static HttpClient newHttpClient(ILoadBalancer loadBalancer, IClientConfig config) { + public static NettyHttpClient newHttpClient(ILoadBalancer loadBalancer, IClientConfig config) { return new NettyHttpClient(loadBalancer, config, getDefaultHttpRetryHandlerWithConfig(config), DEFAULT_HTTP_PIPELINE_CONFIGURATOR, poolCleanerScheduler); } - public static HttpClient newHttpClient(ILoadBalancer loadBalancer, IClientConfig config, RetryHandler retryHandler) { + public static NettyHttpClient newHttpClient(ILoadBalancer loadBalancer, IClientConfig config, RetryHandler retryHandler) { return new NettyHttpClient(loadBalancer, config, retryHandler, DEFAULT_HTTP_PIPELINE_CONFIGURATOR, poolCleanerScheduler); } - public static HttpClient newHttpClient(IClientConfig config) { + public static NettyHttpClient newHttpClient(IClientConfig config) { return new NettyHttpClient(config, getDefaultHttpRetryHandlerWithConfig(config), DEFAULT_HTTP_PIPELINE_CONFIGURATOR, poolCleanerScheduler); } - public static HttpClient newHttpClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, + public static NettyHttpClient newHttpClient(ILoadBalancer loadBalancer) { + IClientConfig config = DefaultClientConfigImpl.getClientConfigWithDefaultValues(); + return newHttpClient(loadBalancer, config); + } + + + public static NettyHttpClient newHttpClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, ILoadBalancer loadBalancer, IClientConfig config) { return new NettyHttpClient(loadBalancer, config, getDefaultHttpRetryHandlerWithConfig(config), pipelineConfigurator, poolCleanerScheduler); } - public static HttpClient newHttpClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, + public static NettyHttpClient newHttpClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, IClientConfig config) { return new NettyHttpClient(config, getDefaultHttpRetryHandlerWithConfig(config), pipelineConfigurator, poolCleanerScheduler); } - public static HttpClient newHttpClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, + public static NettyHttpClient newHttpClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, IClientConfig config, RetryHandler retryHandler) { return new NettyHttpClient(config, retryHandler, pipelineConfigurator, poolCleanerScheduler); } - public static HttpClient newSSEClient(ILoadBalancer loadBalancer, IClientConfig config) { + public static NettyHttpClient newSSEClient(ILoadBalancer loadBalancer, IClientConfig config) { return new SSEClient(loadBalancer, config, getDefaultHttpRetryHandlerWithConfig(config), DEFAULT_SSE_PIPELINE_CONFIGURATOR); } - public static HttpClient newSSEClient(IClientConfig config) { + public static NettyHttpClient newSSEClient(IClientConfig config) { return new SSEClient(config, getDefaultHttpRetryHandlerWithConfig(config), DEFAULT_SSE_PIPELINE_CONFIGURATOR); } - public static HttpClient newSSEClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, + public static NettyHttpClient newSSEClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, ILoadBalancer loadBalancer, IClientConfig config) { return new SSEClient(loadBalancer, config, getDefaultHttpRetryHandlerWithConfig(config), pipelineConfigurator); } - public static HttpClient newSSEClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, + public static NettyHttpClient newSSEClient(PipelineConfigurator, HttpClientRequest> pipelineConfigurator, IClientConfig config) { return new SSEClient(config, getDefaultHttpRetryHandlerWithConfig(config), pipelineConfigurator); } - public static HttpClient newSSEClient() { + public static NettyHttpClient newSSEClient() { IClientConfig config = DefaultClientConfigImpl.getClientConfigWithDefaultValues(); return newSSEClient(config); } diff --git a/ribbon-transport/src/test/java/com/netflix/client/netty/http/NettyClientTest.java b/ribbon-transport/src/test/java/com/netflix/client/netty/http/NettyClientTest.java index 4097c3bb32544cddb0eac6b5cab917d8071345e7..8de5600ba22f941ab1ac200d2d98f9e9fa9ca57e 100644 --- a/ribbon-transport/src/test/java/com/netflix/client/netty/http/NettyClientTest.java +++ b/ribbon-transport/src/test/java/com/netflix/client/netty/http/NettyClientTest.java @@ -612,8 +612,7 @@ public class NettyClientTest { assertEquals("value1", responseContext.get().getContext("Context1")); } - // temporarily exclude the test due to RxNetty bug - @Ignore + @Test public void testRedirect() throws Exception { HttpClientRequest request = HttpClientRequest.createGet(SERVICE_URI + "testAsync/redirect?port=" + port); NettyHttpClient observableClient = (NettyHttpClient) RibbonTransport.newHttpClient();