diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index 648b4084..ca921d35 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1060,6 +1060,8 @@ Zuul's rule engine allows rules and filters to be written in essentially any JVM NOTE: The configuration property `zuul.max.host.connections` has been replaced by two new properties, `zuul.host.maxTotalConnections` and `zuul.host.maxPerRouteConnections` which default to 200 and 20 respectively. +NOTE: Default Hystrix isolation pattern (ExecutionIsolationStrategy) for all routes is SEMAPHORE. `zuul.ribbonIsolationStrategy` can be changed to THREAD if this isolation pattern is preferred. + [[netflix-zuul-reverse-proxy]] === Embedded Zuul Reverse Proxy diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonHttpRequest.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonHttpRequest.java index 2d68b12d..ec610c2c 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonHttpRequest.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonHttpRequest.java @@ -108,6 +108,6 @@ public class RibbonHttpRequest extends AbstractClientHttpRequest { } private boolean isDynamic(String name) { - return name.equalsIgnoreCase("Content-Length") || name.equalsIgnoreCase("Transfer-Encoding"); + return "Content-Length".equalsIgnoreCase(name) || "Transfer-Encoding".equalsIgnoreCase(name); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java index 4ac23b6d..b21d4d40 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java @@ -86,20 +86,24 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @Configuration @ConditionalOnProperty(name = "zuul.ribbon.httpclient.enabled", matchIfMissing = true) protected static class HttpClientRibbonConfiguration { + @Bean @ConditionalOnMissingBean - public RibbonCommandFactory ribbonCommandFactory(SpringClientFactory clientFactory) { - return new HttpClientRibbonCommandFactory(clientFactory); + public RibbonCommandFactory ribbonCommandFactory( + SpringClientFactory clientFactory, ZuulProperties zuulProperties) { + return new HttpClientRibbonCommandFactory(clientFactory, zuulProperties); } } @Configuration @ConditionalOnProperty("zuul.ribbon.restclient.enabled") protected static class RestClientRibbonConfiguration { + @Bean @ConditionalOnMissingBean - public RibbonCommandFactory ribbonCommandFactory(SpringClientFactory clientFactory) { - return new RestClientRibbonCommandFactory(clientFactory); + public RibbonCommandFactory ribbonCommandFactory( + SpringClientFactory clientFactory, ZuulProperties zuulProperties) { + return new RestClientRibbonCommandFactory(clientFactory, zuulProperties); } } @@ -107,10 +111,12 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @ConditionalOnProperty("zuul.ribbon.okhttp.enabled") @ConditionalOnClass(name = "okhttp3.OkHttpClient") protected static class OkHttpRibbonConfiguration { + @Bean @ConditionalOnMissingBean - public RibbonCommandFactory ribbonCommandFactory(SpringClientFactory clientFactory) { - return new OkHttpRibbonCommandFactory(clientFactory); + public RibbonCommandFactory ribbonCommandFactory( + SpringClientFactory clientFactory, ZuulProperties zuulProperties) { + return new OkHttpRibbonCommandFactory(clientFactory, zuulProperties); } } @@ -118,18 +124,16 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @Bean public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) { - return new PreDecorationFilter(routeLocator, - this.server.getServletPrefix(), - this.zuulProperties, - proxyRequestHelper); + return new PreDecorationFilter(routeLocator, this.server.getServletPrefix(), + this.zuulProperties, proxyRequestHelper); } // route filters @Bean public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper, RibbonCommandFactory ribbonCommandFactory) { - RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, - ribbonCommandFactory, this.requestCustomizers); + RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, + this.requestCustomizers); return filter; } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java index 0d49e12b..3bdb633b 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java @@ -31,10 +31,14 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; +import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import static com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE; + /** * @author Spencer Gibb * @author Dave Syer @@ -131,6 +135,10 @@ public class ZuulProperties { */ private boolean sslHostnameValidationEnabled =true; + private ExecutionIsolationStrategy ribbonIsolationStrategy = SEMAPHORE; + + private HystrixSemaphore semaphore = new HystrixSemaphore(); + public Set getIgnoredHeaders() { Set ignoredHeaders = new LinkedHashSet<>(this.ignoredHeaders); if (ClassUtils.isPresent( @@ -298,6 +306,17 @@ public class ZuulProperties { */ private int maxPerRouteConnections = 20; } + + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class HystrixSemaphore { + /** + * The maximum number of total semaphores for Hystrix. + */ + private int maxSemaphores = 100; + + } public String getServletPattern() { String path = this.servletPath; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommand.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommand.java index 2631a3b2..39c850a4 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommand.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommand.java @@ -23,6 +23,7 @@ import java.io.InputStream; import java.net.URI; import java.util.List; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommand; import org.springframework.util.MultiValueMap; @@ -33,23 +34,13 @@ import com.netflix.niws.client.http.RestClient; /** * Hystrix wrapper around Eureka Ribbon command * - * see original - * https://github.com/Netflix/zuul/blob/master/zuul-netflix/src/main/java/com/ - * netflix/zuul/dependency/ribbon/hystrix/RibbonCommand.java + * see original */ @SuppressWarnings("deprecation") public class RestClientRibbonCommand extends AbstractRibbonCommand { - @SuppressWarnings("unused") - @Deprecated - public RestClientRibbonCommand(String commandKey, RestClient restClient, HttpRequest.Verb verb, String uri, - Boolean retryable, MultiValueMap headers, - MultiValueMap params, InputStream requestEntity) { - this(commandKey, restClient, new RibbonCommandContext(commandKey, verb.verb(), uri, retryable, headers, params, requestEntity)); - } - - public RestClientRibbonCommand(String commandKey, RestClient client, RibbonCommandContext context) { - super(commandKey, client, context); + public RestClientRibbonCommand(String commandKey, RestClient client, RibbonCommandContext context, ZuulProperties zuulProperties) { + super(commandKey, client, context, zuulProperties); } @Override diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommandFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommandFactory.java index f5ab494e..9f8718f2 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommandFactory.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommandFactory.java @@ -17,28 +17,32 @@ package org.springframework.cloud.netflix.zuul.filters.route; -import com.netflix.client.http.HttpRequest; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; +import com.netflix.client.http.HttpRequest; import com.netflix.niws.client.http.RestClient; +import lombok.RequiredArgsConstructor; + /** * @author Spencer Gibb */ -public class RestClientRibbonCommandFactory implements RibbonCommandFactory { +@RequiredArgsConstructor +public class RestClientRibbonCommandFactory + implements RibbonCommandFactory { private final SpringClientFactory clientFactory; - public RestClientRibbonCommandFactory(SpringClientFactory clientFactory) { - this.clientFactory = clientFactory; - } + private final ZuulProperties zuulProperties; @Override @SuppressWarnings("deprecation") public RestClientRibbonCommand create(RibbonCommandContext context) { RestClient restClient = this.clientFactory.getClient(context.getServiceId(), RestClient.class); - return new RestClientRibbonCommand(context.getServiceId(), restClient, context); + return new RestClientRibbonCommand(context.getServiceId(), restClient, context, + this.zuulProperties); } public SpringClientFactory getClientFactory() { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonCommandContext.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonCommandContext.java index 173cd09d..a558c5fd 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonCommandContext.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonCommandContext.java @@ -19,7 +19,6 @@ package org.springframework.cloud.netflix.zuul.filters.route; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.List; import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer; @@ -54,17 +53,11 @@ public class RibbonCommandContext { private final List requestCustomizers; private Long contentLength; - public RibbonCommandContext(String serviceId, String method, String uri, Boolean retryable, - MultiValueMap headers, MultiValueMap params, - InputStream requestEntity) { - this(serviceId, method, uri, retryable, headers, params, requestEntity, - new ArrayList(), null); - } - public URI uri() { try { return new URI(this.uri); - } catch (URISyntaxException e) { + } + catch (URISyntaxException e) { ReflectionUtils.rethrowRuntimeException(e); } return null; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java index 8e355424..2df7c7bd 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java @@ -47,8 +47,8 @@ public class RibbonRoutingFilter extends ZuulFilter { protected List requestCustomizers; public RibbonRoutingFilter(ProxyRequestHelper helper, - RibbonCommandFactory ribbonCommandFactory, - List requestCustomizers) { + RibbonCommandFactory ribbonCommandFactory, + List requestCustomizers) { this.helper = helper; this.ribbonCommandFactory = ribbonCommandFactory; this.requestCustomizers = requestCustomizers; @@ -120,12 +120,13 @@ public class RibbonRoutingFilter extends ZuulFilter { uri = uri.replace("//", "/"); return new RibbonCommandContext(serviceId, verb, uri, retryable, headers, params, - requestEntity, this.requestCustomizers); + requestEntity, this.requestCustomizers, request.getContentLengthLong()); } protected ClientHttpResponse forward(RibbonCommandContext context) throws Exception { - Map info = this.helper.debug(context.getMethod(), context.getUri(), - context.getHeaders(), context.getParams(), context.getRequestEntity()); + Map info = this.helper.debug(context.getMethod(), + context.getUri(), context.getHeaders(), context.getParams(), + context.getRequestEntity()); RibbonCommand command = this.ribbonCommandFactory.create(context); try { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommand.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommand.java index e9d17d9c..5061fb1f 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommand.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommand.java @@ -20,6 +20,7 @@ package org.springframework.cloud.netflix.zuul.filters.route.apache; import org.springframework.cloud.netflix.ribbon.apache.RibbonApacheHttpRequest; import org.springframework.cloud.netflix.ribbon.apache.RibbonApacheHttpResponse; import org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommand; @@ -29,8 +30,10 @@ import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibb public class HttpClientRibbonCommand extends AbstractRibbonCommand { public HttpClientRibbonCommand(final String commandKey, - final RibbonLoadBalancingHttpClient client, RibbonCommandContext context) { - super(commandKey, client, context); + final RibbonLoadBalancingHttpClient client, + final RibbonCommandContext context, + final ZuulProperties zuulProperties) { + super(commandKey, client, context, zuulProperties); } @Override diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandFactory.java index 1f3063a6..ec9be369 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandFactory.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandFactory.java @@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.zuul.filters.route.apache; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; @@ -31,6 +32,8 @@ public class HttpClientRibbonCommandFactory implements RibbonCommandFactory { private final SpringClientFactory clientFactory; + + private final ZuulProperties zuulProperties; @Override public HttpClientRibbonCommand create(final RibbonCommandContext context) { @@ -39,7 +42,7 @@ public class HttpClientRibbonCommandFactory implements serviceId, RibbonLoadBalancingHttpClient.class); client.setLoadBalancer(this.clientFactory.getLoadBalancer(serviceId)); - return new HttpClientRibbonCommand(serviceId, client, context); + return new HttpClientRibbonCommand(serviceId, client, context, zuulProperties); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommand.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommand.java index 9709ae16..f66f36b7 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommand.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommand.java @@ -20,6 +20,7 @@ package org.springframework.cloud.netflix.zuul.filters.route.okhttp; import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpLoadBalancingClient; import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpRibbonRequest; import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpRibbonResponse; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommand; @@ -29,8 +30,10 @@ import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibb public class OkHttpRibbonCommand extends AbstractRibbonCommand { public OkHttpRibbonCommand(final String commandKey, - final OkHttpLoadBalancingClient client, RibbonCommandContext context) { - super(commandKey, client, context); + final OkHttpLoadBalancingClient client, + final RibbonCommandContext context, + final ZuulProperties zuulProperties) { + super(commandKey, client, context, zuulProperties); } @Override diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFactory.java index fc65e683..61001443 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFactory.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFactory.java @@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.zuul.filters.route.okhttp; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpLoadBalancingClient; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; @@ -31,6 +32,8 @@ public class OkHttpRibbonCommandFactory implements RibbonCommandFactory { private final SpringClientFactory clientFactory; + + private final ZuulProperties zuulProperties; @Override public OkHttpRibbonCommand create(final RibbonCommandContext context) { @@ -39,7 +42,7 @@ public class OkHttpRibbonCommandFactory implements serviceId, OkHttpLoadBalancingClient.class); client.setLoadBalancer(this.clientFactory.getLoadBalancer(serviceId)); - return new OkHttpRibbonCommand(serviceId, client, context); + return new OkHttpRibbonCommand(serviceId, client, context, zuulProperties); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommand.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommand.java index eb15b4ba..36beb774 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommand.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommand.java @@ -18,10 +18,10 @@ package org.springframework.cloud.netflix.zuul.filters.route.support; import org.springframework.cloud.netflix.ribbon.RibbonHttpResponse; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; import org.springframework.http.client.ClientHttpResponse; -import org.springframework.util.StringUtils; import com.netflix.client.AbstractLoadBalancerAwareClient; import com.netflix.client.ClientRequest; @@ -32,39 +32,48 @@ import com.netflix.hystrix.HystrixCommand; import com.netflix.hystrix.HystrixCommandGroupKey; import com.netflix.hystrix.HystrixCommandKey; import com.netflix.hystrix.HystrixCommandProperties; +import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy; import com.netflix.zuul.constants.ZuulConstants; import com.netflix.zuul.context.RequestContext; /** * @author Spencer Gibb */ -public abstract class AbstractRibbonCommand, RQ extends ClientRequest, RS extends HttpResponse> extends HystrixCommand implements - RibbonCommand { +public abstract class AbstractRibbonCommand, RQ extends ClientRequest, RS extends HttpResponse> + extends HystrixCommand implements RibbonCommand { protected final LBC client; protected RibbonCommandContext context; - public AbstractRibbonCommand(LBC client, RibbonCommandContext context) { - this("default", client, context); + public AbstractRibbonCommand(LBC client, RibbonCommandContext context, + ZuulProperties zuulProperties) { + this("default", client, context, zuulProperties); } - public AbstractRibbonCommand(String commandKey, LBC client, RibbonCommandContext context) { - super(getSetter(commandKey)); + public AbstractRibbonCommand(String commandKey, LBC client, + RibbonCommandContext context, ZuulProperties zuulProperties) { + super(getSetter(commandKey, zuulProperties)); this.client = client; this.context = context; } - protected static Setter getSetter(final String commandKey) { + protected static Setter getSetter(final String commandKey, + ZuulProperties zuulProperties) { - // we want to default to semaphore-isolation since this wraps - // 2 others commands that are already thread isolated // @formatter:off - final String name = ZuulConstants.ZUUL_EUREKA + commandKey + ".semaphore.maxSemaphores"; - final DynamicIntProperty value = DynamicPropertyFactory.getInstance() - .getIntProperty(name, 100); - final HystrixCommandProperties.Setter setter = HystrixCommandProperties .Setter() - .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE) - .withExecutionIsolationSemaphoreMaxConcurrentRequests(value.get()); + final HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() + .withExecutionIsolationStrategy(zuulProperties.getRibbonIsolationStrategy()); + if (zuulProperties.getRibbonIsolationStrategy() == ExecutionIsolationStrategy.SEMAPHORE){ + final String name = ZuulConstants.ZUUL_EUREKA + commandKey + ".semaphore.maxSemaphores"; + // we want to default to semaphore-isolation since this wraps + // 2 others commands that are already thread isolated + final DynamicIntProperty value = DynamicPropertyFactory.getInstance() + .getIntProperty(name, 100); + setter.withExecutionIsolationSemaphoreMaxConcurrentRequests(value.get()); + } else { + // TODO Find out is some parameters can be set here + } + return Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("RibbonCommand")) .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey + "RibbonCommand")) .andCommandPropertiesDefaults(setter); @@ -74,10 +83,6 @@ public abstract class AbstractRibbonCommand headers = new LinkedMultiValueMap<>(); headers.add("my-header", "my-value"); + headers.add(HttpEncoding.CONTENT_LENGTH, "5192"); LinkedMultiValueMap params = new LinkedMultiValueMap<>(); params.add("myparam", "myparamval"); - RibbonApacheHttpRequest httpRequest = new RibbonApacheHttpRequest(new RibbonCommandContext("example", "GET", uri, false, - headers, params, null)); + RibbonApacheHttpRequest httpRequest = + new RibbonApacheHttpRequest( + new RibbonCommandContext("example", "GET", uri, false, headers, params, null, new ArrayList())); HttpUriRequest request = httpRequest.toRequest(RequestConfig.custom().build()); @@ -63,7 +67,9 @@ public class RibbonApacheHttpRequestTests { assertThat("uri is wrong", request.getURI().toString(), startsWith(uri)); assertThat("my-header is missing", request.getFirstHeader("my-header"), is(notNullValue())); assertThat("my-header is wrong", request.getFirstHeader("my-header").getValue(), is(equalTo("my-value"))); + assertThat("Content-Length is wrong", request.getFirstHeader(HttpEncoding.CONTENT_LENGTH).getValue(), is(equalTo("5192"))); assertThat("myparam is missing", request.getURI().getQuery(), is(equalTo("myparam=myparamval"))); + } @Test diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonRequestTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonRequestTests.java index 4c6c84fd..d35ea62d 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonRequestTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonRequestTests.java @@ -26,9 +26,11 @@ import static org.junit.Assert.assertThat; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import org.junit.Test; +import org.springframework.cloud.netflix.feign.encoding.HttpEncoding; import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; import org.springframework.util.LinkedMultiValueMap; @@ -47,33 +49,41 @@ public class OkHttpRibbonRequestTests { String uri = "http://example.com"; LinkedMultiValueMap headers = new LinkedMultiValueMap<>(); headers.add("my-header", "my-value"); + // headers.add(HttpEncoding.CONTENT_LENGTH, "5192"); LinkedMultiValueMap params = new LinkedMultiValueMap<>(); params.add("myparam", "myparamval"); - RibbonCommandContext context = new RibbonCommandContext("example", "GET", uri, false, headers, params, null); + RibbonCommandContext context = new RibbonCommandContext("example", "GET", uri, + false, headers, params, null, new ArrayList()); OkHttpRibbonRequest httpRequest = new OkHttpRibbonRequest(context); Request request = httpRequest.toRequest(); assertThat("body is not null", request.body(), is(nullValue())); assertThat("uri is wrong", request.url().toString(), startsWith(uri)); - assertThat("my-header is wrong", request.header("my-header"), is(equalTo("my-value"))); - assertThat("myparam is missing", request.url().queryParameter("myparam"), is(equalTo("myparamval"))); + assertThat("my-header is wrong", request.header("my-header"), + is(equalTo("my-value"))); + assertThat("myparam is missing", request.url().queryParameter("myparam"), + is(equalTo("myparamval"))); } @Test - // this situation happens, see https://github.com/spring-cloud/spring-cloud-netflix/issues/1042#issuecomment-227723877 + // this situation happens, see + // https://github.com/spring-cloud/spring-cloud-netflix/issues/1042#issuecomment-227723877 public void testEmptyEntityGet() throws Exception { String entityValue = ""; - testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), false, "GET"); + testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), false, + "GET"); } @Test public void testNonEmptyEntityPost() throws Exception { String entityValue = "abcd"; - testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), true, "POST"); + testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), true, + "POST"); } - void testEntity(String entityValue, ByteArrayInputStream requestEntity, boolean addContentLengthHeader, String method) throws IOException { + void testEntity(String entityValue, ByteArrayInputStream requestEntity, + boolean addContentLengthHeader, String method) throws IOException { String lengthString = String.valueOf(entityValue.length()); Long length = null; String uri = "http://example.com"; @@ -94,8 +104,9 @@ public class OkHttpRibbonRequestTests { builder.addHeader("from-customizer", "foo"); } }; - RibbonCommandContext context = new RibbonCommandContext("example", method, uri, false, - headers, new LinkedMultiValueMap(), requestEntity, Collections.singletonList(requestCustomizer)); + RibbonCommandContext context = new RibbonCommandContext("example", method, uri, + false, headers, new LinkedMultiValueMap(), requestEntity, + Collections.singletonList(requestCustomizer)); context.setContentLength(length); OkHttpRibbonRequest httpRequest = new OkHttpRibbonRequest(context); @@ -112,7 +123,8 @@ public class OkHttpRibbonRequestTests { if (!method.equalsIgnoreCase("get")) { assertThat("body is null", request.body(), is(notNullValue())); RequestBody body = request.body(); - assertThat("contentLength is wrong", body.contentLength(), is(equalTo((long) entityValue.length()))); + assertThat("contentLength is wrong", body.contentLength(), + is(equalTo((long) entityValue.length()))); Buffer content = new Buffer(); body.writeTo(content); String string = content.readByteString().utf8(); @@ -120,4 +132,3 @@ public class OkHttpRibbonRequestTests { } } } - diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommandTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommandTests.java index f8d43345..5b4671d4 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommandTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommandTests.java @@ -27,10 +27,13 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.net.URI; import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.Collections; +import org.junit.Before; import org.junit.Test; import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.StreamUtils; @@ -41,6 +44,13 @@ import com.netflix.client.http.HttpRequest; */ public class RestClientRibbonCommandTests { + private ZuulProperties zuulProperties; + + @Before + public void setUp() { + zuulProperties = new ZuulProperties(); + } + @Test public void testNullEntity() throws Exception { String uri = "http://example.com"; @@ -48,8 +58,10 @@ public class RestClientRibbonCommandTests { headers.add("my-header", "my-value"); LinkedMultiValueMap params = new LinkedMultiValueMap<>(); params.add("myparam", "myparamval"); - RestClientRibbonCommand command = new RestClientRibbonCommand("cmd", null, new RibbonCommandContext("example", "GET", uri, false, - headers, params, null)); + RestClientRibbonCommand command = + new RestClientRibbonCommand("cmd", null, + new RibbonCommandContext("example", "GET", uri, false, headers, params, null,new ArrayList()), + zuulProperties); HttpRequest request = command.createRequest(); @@ -96,7 +108,7 @@ public class RestClientRibbonCommandTests { uri.toString(), false, headers, new LinkedMultiValueMap(), requestEntity, Collections.singletonList(requestCustomizer)); context.setContentLength(length); - RestClientRibbonCommand command = new RestClientRibbonCommand("cmd", null, context); + RestClientRibbonCommand command = new RestClientRibbonCommand("cmd", null, context, zuulProperties); HttpRequest request = command.createRequest(); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandIntegrationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandIntegrationTests.java index d4bcfa2c..e6765192 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandIntegrationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandIntegrationTests.java @@ -41,6 +41,7 @@ import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.StaticServerList; import org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; import org.springframework.cloud.netflix.zuul.filters.route.support.ZuulProxyTestBase; import org.springframework.context.annotation.Bean; @@ -179,7 +180,7 @@ public class HttpClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { @Bean public RibbonCommandFactory ribbonCommandFactory( final SpringClientFactory clientFactory) { - return new HttpClientRibbonCommandFactory(clientFactory); + return new HttpClientRibbonCommandFactory(clientFactory, new ZuulProperties()); } @Bean diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandIntegrationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandIntegrationTests.java index 7c4086f8..023e7abe 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandIntegrationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandIntegrationTests.java @@ -32,6 +32,7 @@ import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.cloud.netflix.ribbon.RibbonClients; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; import org.springframework.cloud.netflix.zuul.filters.route.support.ZuulProxyTestBase; import org.springframework.context.annotation.Bean; @@ -107,7 +108,7 @@ public class OkHttpRibbonCommandIntegrationTests extends ZuulProxyTestBase { @Bean public RibbonCommandFactory ribbonCommandFactory( final SpringClientFactory clientFactory) { - return new OkHttpRibbonCommandFactory(clientFactory); + return new OkHttpRibbonCommandFactory(clientFactory, new ZuulProperties()); } @Bean diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java index bb905634..3a88e5c5 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java @@ -330,7 +330,7 @@ public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { private SpringClientFactory clientFactory; public MyRibbonCommandFactory(SpringClientFactory clientFactory) { - super(clientFactory); + super(clientFactory, new ZuulProperties()); this.clientFactory = clientFactory; } @@ -356,7 +356,7 @@ public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { public MyCommand(int errorCode, String commandKey, RestClient restClient, RibbonCommandContext context) { - super(commandKey, restClient, context); + super(commandKey, restClient, context, new ZuulProperties()); this.errorCode = errorCode; }