Merge branch 'stephlag-zuul_hystrix_threadpool'
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<String> getIgnoredHeaders() {
|
||||
Set<String> 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;
|
||||
|
||||
@@ -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 <a href="https://github.com/Netflix/zuul/blob/master/zuul-netflix/src/main/java/com/netflix/zuul/dependency/ribbon/hystrix/RibbonCommand.java">original</a>
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class RestClientRibbonCommand extends AbstractRibbonCommand<RestClient, HttpRequest, HttpResponse> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated
|
||||
public RestClientRibbonCommand(String commandKey, RestClient restClient, HttpRequest.Verb verb, String uri,
|
||||
Boolean retryable, MultiValueMap<String, String> headers,
|
||||
MultiValueMap<String, String> 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
|
||||
|
||||
@@ -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<RestClientRibbonCommand> {
|
||||
@RequiredArgsConstructor
|
||||
public class RestClientRibbonCommandFactory
|
||||
implements RibbonCommandFactory<RestClientRibbonCommand> {
|
||||
|
||||
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() {
|
||||
|
||||
@@ -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<RibbonRequestCustomizer> requestCustomizers;
|
||||
private Long contentLength;
|
||||
|
||||
public RibbonCommandContext(String serviceId, String method, String uri, Boolean retryable,
|
||||
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
|
||||
InputStream requestEntity) {
|
||||
this(serviceId, method, uri, retryable, headers, params, requestEntity,
|
||||
new ArrayList<RibbonRequestCustomizer>(), null);
|
||||
}
|
||||
|
||||
public URI uri() {
|
||||
try {
|
||||
return new URI(this.uri);
|
||||
} catch (URISyntaxException e) {
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
ReflectionUtils.rethrowRuntimeException(e);
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -47,8 +47,8 @@ public class RibbonRoutingFilter extends ZuulFilter {
|
||||
protected List<RibbonRequestCustomizer> requestCustomizers;
|
||||
|
||||
public RibbonRoutingFilter(ProxyRequestHelper helper,
|
||||
RibbonCommandFactory<?> ribbonCommandFactory,
|
||||
List<RibbonRequestCustomizer> requestCustomizers) {
|
||||
RibbonCommandFactory<?> ribbonCommandFactory,
|
||||
List<RibbonRequestCustomizer> 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<String, Object> info = this.helper.debug(context.getMethod(), context.getUri(),
|
||||
context.getHeaders(), context.getParams(), context.getRequestEntity());
|
||||
Map<String, Object> info = this.helper.debug(context.getMethod(),
|
||||
context.getUri(), context.getHeaders(), context.getParams(),
|
||||
context.getRequestEntity());
|
||||
|
||||
RibbonCommand command = this.ribbonCommandFactory.create(context);
|
||||
try {
|
||||
|
||||
@@ -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<RibbonLoadBalancingHttpClient, RibbonApacheHttpRequest, RibbonApacheHttpResponse> {
|
||||
|
||||
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
|
||||
|
||||
@@ -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<HttpClientRibbonCommand> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<OkHttpLoadBalancingClient, OkHttpRibbonRequest, OkHttpRibbonResponse> {
|
||||
|
||||
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
|
||||
|
||||
@@ -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<OkHttpRibbonCommand> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<LBC extends AbstractLoadBalancerAwareClient<RQ, RS>, RQ extends ClientRequest, RS extends HttpResponse> extends HystrixCommand<ClientHttpResponse> implements
|
||||
RibbonCommand {
|
||||
public abstract class AbstractRibbonCommand<LBC extends AbstractLoadBalancerAwareClient<RQ, RS>, RQ extends ClientRequest, RS extends HttpResponse>
|
||||
extends HystrixCommand<ClientHttpResponse> 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<LBC extends AbstractLoadBalancerAwar
|
||||
@Override
|
||||
protected ClientHttpResponse run() throws Exception {
|
||||
final RequestContext context = RequestContext.getCurrentContext();
|
||||
long contentLength = context.getRequest().getContentLengthLong();
|
||||
if (contentLength != -1) {
|
||||
this.context.setContentLength(contentLength);
|
||||
}
|
||||
|
||||
RQ request = createRequest();
|
||||
RS response = this.client.executeWithLoadBalancer(request);
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
@@ -37,6 +38,7 @@ import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.client.methods.RequestBuilder;
|
||||
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;
|
||||
@@ -52,10 +54,12 @@ public class RibbonApacheHttpRequestTests {
|
||||
String uri = "http://example.com";
|
||||
LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
headers.add("my-header", "my-value");
|
||||
headers.add(HttpEncoding.CONTENT_LENGTH, "5192");
|
||||
LinkedMultiValueMap<String, String> 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<RibbonRequestCustomizer>()));
|
||||
|
||||
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
|
||||
|
||||
@@ -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<String, String> headers = new LinkedMultiValueMap<>();
|
||||
headers.add("my-header", "my-value");
|
||||
// headers.add(HttpEncoding.CONTENT_LENGTH, "5192");
|
||||
LinkedMultiValueMap<String, String> 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<RibbonRequestCustomizer>());
|
||||
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<String, String>(), requestEntity, Collections.singletonList(requestCustomizer));
|
||||
RibbonCommandContext context = new RibbonCommandContext("example", method, uri,
|
||||
false, headers, new LinkedMultiValueMap<String, String>(), 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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<String, String> 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<RibbonRequestCustomizer>()),
|
||||
zuulProperties);
|
||||
|
||||
HttpRequest request = command.createRequest();
|
||||
|
||||
@@ -96,7 +108,7 @@ public class RestClientRibbonCommandTests {
|
||||
uri.toString(), false, headers, new LinkedMultiValueMap<String, String>(),
|
||||
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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user