Commit 8029deb1 by Ryan Baxter

Merging PR #1457 into master.

parent 5ee9990d
...@@ -41,6 +41,7 @@ import com.netflix.hystrix.HystrixCommand; ...@@ -41,6 +41,7 @@ import com.netflix.hystrix.HystrixCommand;
import feign.Contract; import feign.Contract;
import feign.Feign; import feign.Feign;
import feign.Logger; import feign.Logger;
import feign.Retryer;
import feign.codec.Decoder; import feign.codec.Decoder;
import feign.codec.Encoder; import feign.codec.Encoder;
import feign.hystrix.HystrixFeign; import feign.hystrix.HystrixFeign;
...@@ -107,7 +108,7 @@ public class FeignClientsConfiguration { ...@@ -107,7 +108,7 @@ public class FeignClientsConfiguration {
@Scope("prototype") @Scope("prototype")
@ConditionalOnMissingBean @ConditionalOnMissingBean
public Feign.Builder feignBuilder() { public Feign.Builder feignBuilder() {
return Feign.builder(); return Feign.builder().retryer(Retryer.NEVER_RETRY);
} }
@Bean @Bean
......
...@@ -16,14 +16,15 @@ ...@@ -16,14 +16,15 @@
package org.springframework.cloud.netflix.feign.ribbon; package org.springframework.cloud.netflix.feign.ribbon;
import java.util.Map; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector; import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.ConcurrentReferenceHashMap;
import com.netflix.client.config.IClientConfig; import java.util.Map;
import com.netflix.loadbalancer.ILoadBalancer;
/** /**
* Factory for SpringLoadBalancer instances that caches the entries created. * Factory for SpringLoadBalancer instances that caches the entries created.
...@@ -34,11 +35,16 @@ import com.netflix.loadbalancer.ILoadBalancer; ...@@ -34,11 +35,16 @@ import com.netflix.loadbalancer.ILoadBalancer;
public class CachingSpringLoadBalancerFactory { public class CachingSpringLoadBalancerFactory {
private final SpringClientFactory factory; private final SpringClientFactory factory;
private final RetryTemplate retryTemplate;
private final LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory;
private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>(); private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();
public CachingSpringLoadBalancerFactory(SpringClientFactory factory) { public CachingSpringLoadBalancerFactory(SpringClientFactory factory, RetryTemplate retryTemplate,
LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory) {
this.factory = factory; this.factory = factory;
this.retryTemplate = retryTemplate;
this.loadBalancedRetryPolicyFactory = loadBalancedRetryPolicyFactory;
} }
public FeignLoadBalancer create(String clientName) { public FeignLoadBalancer create(String clientName) {
...@@ -48,7 +54,8 @@ public class CachingSpringLoadBalancerFactory { ...@@ -48,7 +54,8 @@ public class CachingSpringLoadBalancerFactory {
IClientConfig config = this.factory.getClientConfig(clientName); IClientConfig config = this.factory.getClientConfig(clientName);
ILoadBalancer lb = this.factory.getLoadBalancer(clientName); ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class); ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
FeignLoadBalancer client = new FeignLoadBalancer(lb, config, serverIntrospector); FeignLoadBalancer client = new FeignLoadBalancer(lb, config, serverIntrospector, retryTemplate,
loadBalancedRetryPolicyFactory);
this.cache.put(clientName, client); this.cache.put(clientName, client);
return client; return client;
} }
......
...@@ -16,44 +16,65 @@ ...@@ -16,44 +16,65 @@
package org.springframework.cloud.netflix.feign.ribbon; package org.springframework.cloud.netflix.feign.ribbon;
import java.io.IOException;
import java.net.URI;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import com.netflix.client.AbstractLoadBalancerAwareClient; import com.netflix.client.AbstractLoadBalancerAwareClient;
import com.netflix.client.ClientException; import com.netflix.client.ClientException;
import com.netflix.client.ClientRequest; import com.netflix.client.ClientRequest;
import com.netflix.client.DefaultLoadBalancerRetryHandler;
import com.netflix.client.IResponse; import com.netflix.client.IResponse;
import com.netflix.client.RequestSpecificRetryHandler; import com.netflix.client.RequestSpecificRetryHandler;
import com.netflix.client.RetryHandler;
import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import feign.Client; import feign.Client;
import feign.Request; import feign.Request;
import feign.Response; import feign.Response;
import feign.Util; import feign.Util;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.InterceptorRetryPolicy;
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext;
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicy;
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory;
import org.springframework.cloud.client.loadbalancer.ServiceInstanceChooser;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.policy.NeverRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttpsIfNeeded; import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttpsIfNeeded;
public class FeignLoadBalancer extends public class FeignLoadBalancer extends
AbstractLoadBalancerAwareClient<FeignLoadBalancer.RibbonRequest, FeignLoadBalancer.RibbonResponse> { AbstractLoadBalancerAwareClient<FeignLoadBalancer.RibbonRequest, FeignLoadBalancer.RibbonResponse> implements
ServiceInstanceChooser {
private final int connectTimeout; private final int connectTimeout;
private final int readTimeout; private final int readTimeout;
private final IClientConfig clientConfig; private final IClientConfig clientConfig;
private final ServerIntrospector serverIntrospector; private final ServerIntrospector serverIntrospector;
private final RetryTemplate retryTemplate;
private final LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory;
public FeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig, public FeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig,
ServerIntrospector serverIntrospector) { ServerIntrospector serverIntrospector, RetryTemplate retryTemplate,
LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory) {
super(lb, clientConfig); super(lb, clientConfig);
this.setRetryHandler(RetryHandler.DEFAULT); this.retryTemplate = retryTemplate;
this.loadBalancedRetryPolicyFactory = loadBalancedRetryPolicyFactory;
this.setRetryHandler(new DefaultLoadBalancerRetryHandler(clientConfig));
this.clientConfig = clientConfig; this.clientConfig = clientConfig;
this.connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout); this.connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout);
this.readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout); this.readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout);
...@@ -61,9 +82,9 @@ public class FeignLoadBalancer extends ...@@ -61,9 +82,9 @@ public class FeignLoadBalancer extends
} }
@Override @Override
public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride) public RibbonResponse execute(final RibbonRequest request, IClientConfig configOverride)
throws IOException { throws IOException {
Request.Options options; final Request.Options options;
if (configOverride != null) { if (configOverride != null) {
options = new Request.Options( options = new Request.Options(
configOverride.get(CommonClientConfigKey.ConnectTimeout, configOverride.get(CommonClientConfigKey.ConnectTimeout,
...@@ -74,26 +95,45 @@ public class FeignLoadBalancer extends ...@@ -74,26 +95,45 @@ public class FeignLoadBalancer extends
else { else {
options = new Request.Options(this.connectTimeout, this.readTimeout); options = new Request.Options(this.connectTimeout, this.readTimeout);
} }
Response response = request.client().execute(request.toRequest(), options); LoadBalancedRetryPolicy retryPolicy = loadBalancedRetryPolicyFactory.create(this.getClientName(), this);
return new RibbonResponse(request.getUri(), response); retryTemplate.setRetryPolicy(retryPolicy == null ? new NeverRetryPolicy()
: new InterceptorRetryPolicy(request.toHttpRequest(), retryPolicy, this, this.getClientName()));
return retryTemplate.execute(new RetryCallback<RibbonResponse, IOException>() {
@Override
public RibbonResponse doWithRetry(RetryContext retryContext) throws IOException {
Request feignRequest = null;
if(retryContext instanceof LoadBalancedRetryContext) {
ServiceInstance service = ((LoadBalancedRetryContext)retryContext).getServiceInstance();
if(service != null) {
feignRequest = ((RibbonRequest)request.replaceUri(reconstructURIWithServer(new Server(service.getHost(), service.getPort()), request.getUri()))).toRequest();
}
}
if(feignRequest == null) {
feignRequest = request.toRequest();
}
Response response = request.client().execute(feignRequest, options);
return new RibbonResponse(request.getUri(), response);
}
});
} }
@Override @Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler( public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonRequest request, IClientConfig requestConfig) { RibbonRequest request, IClientConfig requestConfig) {
if (this.clientConfig.get(CommonClientConfigKey.OkToRetryOnAllOperations, // if (this.clientConfig.get(CommonClientConfigKey.OkToRetryOnAllOperations,
false)) { // false)) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), // return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
requestConfig); // requestConfig);
} // }
if (!request.toRequest().method().equals("GET")) { // if (!request.toRequest().method().equals("GET")) {
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(), // return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(),
requestConfig); // requestConfig);
} // }
else { // else {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), // return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
requestConfig); // requestConfig);
} // }
return new RequestSpecificRetryHandler(false, false, this.getRetryHandler(), requestConfig);
} }
@Override @Override
...@@ -102,6 +142,12 @@ public class FeignLoadBalancer extends ...@@ -102,6 +142,12 @@ public class FeignLoadBalancer extends
return super.reconstructURIWithServer(server, uri); return super.reconstructURIWithServer(server, uri);
} }
@Override
public ServiceInstance choose(String serviceId) {
return new RibbonLoadBalancerClient.RibbonServer(serviceId,
this.getLoadBalancer().chooseServer(serviceId));
}
static class RibbonRequest extends ClientRequest implements Cloneable { static class RibbonRequest extends ClientRequest implements Cloneable {
private final Request request; private final Request request;
...@@ -129,6 +175,33 @@ public class FeignLoadBalancer extends ...@@ -129,6 +175,33 @@ public class FeignLoadBalancer extends
return this.client; return this.client;
} }
HttpRequest toHttpRequest() {
return new HttpRequest() {
@Override
public HttpMethod getMethod() {
return HttpMethod.resolve(RibbonRequest.this.toRequest().method());
}
@Override
public URI getURI() {
return RibbonRequest.this.getUri();
}
@Override
public HttpHeaders getHeaders() {
Map<String, List<String>> headers = new HashMap<String, List<String>>();
Map<String, Collection<String>> feignHeaders = RibbonRequest.this.toRequest().headers();
for(String key : feignHeaders.keySet()) {
headers.put(key, new ArrayList<String>(feignHeaders.get(key)));
}
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(headers);
return httpHeaders;
}
};
}
@Override @Override
public Object clone() { public Object clone() {
return new RibbonRequest(this.client, this.request, getUri()); return new RibbonRequest(this.client, this.request, getUri());
......
...@@ -22,11 +22,13 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore; ...@@ -22,11 +22,13 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory;
import org.springframework.cloud.netflix.feign.FeignAutoConfiguration; import org.springframework.cloud.netflix.feign.FeignAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.retry.support.RetryTemplate;
import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.ILoadBalancer;
...@@ -50,8 +52,16 @@ public class FeignRibbonClientAutoConfiguration { ...@@ -50,8 +52,16 @@ public class FeignRibbonClientAutoConfiguration {
@Bean @Bean
@Primary @Primary
public CachingSpringLoadBalancerFactory cachingLBClientFactory( public CachingSpringLoadBalancerFactory cachingLBClientFactory(
SpringClientFactory factory) { SpringClientFactory factory, LoadBalancedRetryPolicyFactory retryPolicyFactory,
return new CachingSpringLoadBalancerFactory(factory); RetryTemplate retryTemplate) {
return new CachingSpringLoadBalancerFactory(factory, retryTemplate, retryPolicyFactory);
}
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate template = new RetryTemplate();
template.setThrowLastExceptionOnExhausted(true);
return template;
} }
@Bean @Bean
......
...@@ -141,17 +141,17 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { ...@@ -141,17 +141,17 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient {
return this.clientFactory.getLoadBalancer(serviceId); return this.clientFactory.getLoadBalancer(serviceId);
} }
protected static class RibbonServer implements ServiceInstance { public static class RibbonServer implements ServiceInstance {
private final String serviceId; private final String serviceId;
private final Server server; private final Server server;
private final boolean secure; private final boolean secure;
private Map<String, String> metadata; private Map<String, String> metadata;
protected RibbonServer(String serviceId, Server server) { public RibbonServer(String serviceId, Server server) {
this(serviceId, server, false, Collections.<String, String> emptyMap()); this(serviceId, server, false, Collections.<String, String> emptyMap());
} }
protected RibbonServer(String serviceId, Server server, boolean secure, public RibbonServer(String serviceId, Server server, boolean secure,
Map<String, String> metadata) { Map<String, String> metadata) {
this.serviceId = serviceId; this.serviceId = serviceId;
this.server = server; this.server = server;
......
...@@ -16,8 +16,12 @@ ...@@ -16,8 +16,12 @@
package org.springframework.cloud.netflix.ribbon.apache; package org.springframework.cloud.netflix.ribbon.apache;
import java.net.URI; import com.netflix.client.RequestSpecificRetryHandler;
import com.netflix.client.RetryHandler;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
...@@ -27,10 +31,7 @@ import org.springframework.cloud.netflix.ribbon.ServerIntrospector; ...@@ -27,10 +31,7 @@ import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.support.AbstractLoadBalancingClient; import org.springframework.cloud.netflix.ribbon.support.AbstractLoadBalancingClient;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import com.netflix.client.config.CommonClientConfigKey; import java.net.URI;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttpsIfNeeded; import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttpsIfNeeded;
...@@ -102,4 +103,9 @@ public class RibbonLoadBalancingHttpClient ...@@ -102,4 +103,9 @@ public class RibbonLoadBalancingHttpClient
return super.reconstructURIWithServer(server, uri); return super.reconstructURIWithServer(server, uri);
} }
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(RibbonApacheHttpRequest request, IClientConfig requestConfig) {
return new RequestSpecificRetryHandler(false, false, RetryHandler.DEFAULT, null);
}
} }
...@@ -16,6 +16,15 @@ ...@@ -16,6 +16,15 @@
package org.springframework.cloud.netflix.zuul.filters; package org.springframework.cloud.netflix.zuul.filters;
import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
...@@ -25,18 +34,6 @@ import java.util.Map; ...@@ -25,18 +34,6 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import javax.annotation.PostConstruct;
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; import static com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE;
/** /**
...@@ -71,7 +68,7 @@ public class ZuulProperties { ...@@ -71,7 +68,7 @@ public class ZuulProperties {
* Flag for whether retry is supported by default (assuming the routes themselves * Flag for whether retry is supported by default (assuming the routes themselves
* support it). * support it).
*/ */
private Boolean retryable; private Boolean retryable = false;
/** /**
* Map of route names to properties. * Map of route names to properties.
......
...@@ -16,20 +16,21 @@ ...@@ -16,20 +16,21 @@
package org.springframework.cloud.netflix.feign.ribbon; package org.springframework.cloud.netflix.feign.ribbon;
import static org.junit.Assert.assertNotNull; import com.netflix.client.config.CommonClientConfigKey;
import static org.mockito.Mockito.times; import com.netflix.client.config.DefaultClientConfigImpl;
import static org.mockito.Mockito.verify; import com.netflix.client.config.IClientConfig;
import static org.mockito.Mockito.when;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryPolicyFactory;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.retry.support.RetryTemplate;
import com.netflix.client.config.CommonClientConfigKey; import static org.junit.Assert.assertNotNull;
import com.netflix.client.config.DefaultClientConfigImpl; import static org.mockito.Mockito.times;
import com.netflix.client.config.IClientConfig; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
...@@ -39,6 +40,9 @@ public class CachingSpringLoadBalancerFactoryTests { ...@@ -39,6 +40,9 @@ public class CachingSpringLoadBalancerFactoryTests {
@Mock @Mock
private SpringClientFactory delegate; private SpringClientFactory delegate;
@Mock
private RibbonLoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory;
private CachingSpringLoadBalancerFactory factory; private CachingSpringLoadBalancerFactory factory;
@Before @Before
...@@ -52,7 +56,8 @@ public class CachingSpringLoadBalancerFactoryTests { ...@@ -52,7 +56,8 @@ public class CachingSpringLoadBalancerFactoryTests {
when(this.delegate.getClientConfig("client1")).thenReturn(config); when(this.delegate.getClientConfig("client1")).thenReturn(config);
when(this.delegate.getClientConfig("client2")).thenReturn(config); when(this.delegate.getClientConfig("client2")).thenReturn(config);
this.factory = new CachingSpringLoadBalancerFactory(this.delegate); this.factory = new CachingSpringLoadBalancerFactory(this.delegate, new RetryTemplate(),
loadBalancedRetryPolicyFactory);
} }
@Test @Test
......
package org.springframework.cloud.netflix.feign.ribbon; package org.springframework.cloud.netflix.feign.ribbon;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import feign.Client;
import feign.Request;
import feign.Request.Options;
import feign.RequestTemplate;
import feign.Response;
import lombok.SneakyThrows;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.cloud.netflix.feign.ribbon.FeignLoadBalancer.RibbonRequest;
import org.springframework.cloud.netflix.feign.ribbon.FeignLoadBalancer.RibbonResponse;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryPolicyFactory;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.retry.support.RetryTemplate;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static com.netflix.client.config.CommonClientConfigKey.ConnectTimeout; import static com.netflix.client.config.CommonClientConfigKey.ConnectTimeout;
import static com.netflix.client.config.CommonClientConfigKey.IsSecure; import static com.netflix.client.config.CommonClientConfigKey.IsSecure;
import static com.netflix.client.config.CommonClientConfigKey.MaxAutoRetries; import static com.netflix.client.config.CommonClientConfigKey.MaxAutoRetries;
...@@ -15,33 +42,6 @@ import static org.mockito.Matchers.anyBoolean; ...@@ -15,33 +42,6 @@ import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.cloud.netflix.feign.ribbon.FeignLoadBalancer.RibbonRequest;
import org.springframework.cloud.netflix.feign.ribbon.FeignLoadBalancer.RibbonResponse;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import feign.Client;
import feign.Request;
import feign.Request.Options;
import feign.RequestTemplate;
import feign.Response;
import lombok.SneakyThrows;
public class FeignLoadBalancerTests { public class FeignLoadBalancerTests {
@Mock @Mock
...@@ -50,6 +50,9 @@ public class FeignLoadBalancerTests { ...@@ -50,6 +50,9 @@ public class FeignLoadBalancerTests {
private ILoadBalancer lb; private ILoadBalancer lb;
@Mock @Mock
private IClientConfig config; private IClientConfig config;
@Mock
private RibbonLoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory;
private RetryTemplate retryTemplate;
private FeignLoadBalancer feignLoadBalancer; private FeignLoadBalancer feignLoadBalancer;
...@@ -68,6 +71,7 @@ public class FeignLoadBalancerTests { ...@@ -68,6 +71,7 @@ public class FeignLoadBalancerTests {
.thenReturn(true); .thenReturn(true);
when(this.config.get(ConnectTimeout)).thenReturn(this.defaultConnectTimeout); when(this.config.get(ConnectTimeout)).thenReturn(this.defaultConnectTimeout);
when(this.config.get(ReadTimeout)).thenReturn(this.defaultReadTimeout); when(this.config.get(ReadTimeout)).thenReturn(this.defaultReadTimeout);
this.retryTemplate = new RetryTemplate();
} }
@Test @Test
...@@ -75,7 +79,7 @@ public class FeignLoadBalancerTests { ...@@ -75,7 +79,7 @@ public class FeignLoadBalancerTests {
public void testUriInsecure() { public void testUriInsecure() {
when(this.config.get(IsSecure)).thenReturn(false); when(this.config.get(IsSecure)).thenReturn(false);
this.feignLoadBalancer = new FeignLoadBalancer(this.lb, this.config, this.feignLoadBalancer = new FeignLoadBalancer(this.lb, this.config,
this.inspector); this.inspector, retryTemplate, loadBalancedRetryPolicyFactory);
Request request = new RequestTemplate().method("GET").append("http://foo/") Request request = new RequestTemplate().method("GET").append("http://foo/")
.request(); .request();
RibbonRequest ribbonRequest = new RibbonRequest(this.delegate, request, RibbonRequest ribbonRequest = new RibbonRequest(this.delegate, request,
...@@ -96,7 +100,7 @@ public class FeignLoadBalancerTests { ...@@ -96,7 +100,7 @@ public class FeignLoadBalancerTests {
public void testSecureUriFromClientConfig() { public void testSecureUriFromClientConfig() {
when(this.config.get(IsSecure)).thenReturn(true); when(this.config.get(IsSecure)).thenReturn(true);
this.feignLoadBalancer = new FeignLoadBalancer(this.lb, this.config, this.feignLoadBalancer = new FeignLoadBalancer(this.lb, this.config,
this.inspector); this.inspector, retryTemplate, loadBalancedRetryPolicyFactory);
Server server = new Server("foo", 7777); Server server = new Server("foo", 7777);
URI uri = this.feignLoadBalancer.reconstructURIWithServer(server, URI uri = this.feignLoadBalancer.reconstructURIWithServer(server,
new URI("http://foo/")); new URI("http://foo/"));
...@@ -118,7 +122,7 @@ public class FeignLoadBalancerTests { ...@@ -118,7 +122,7 @@ public class FeignLoadBalancerTests {
public Map<String, String> getMetadata(Server server) { public Map<String, String> getMetadata(Server server) {
return null; return null;
} }
}); }, retryTemplate, loadBalancedRetryPolicyFactory);
Server server = new Server("foo", 7777); Server server = new Server("foo", 7777);
URI uri = this.feignLoadBalancer.reconstructURIWithServer(server, URI uri = this.feignLoadBalancer.reconstructURIWithServer(server,
new URI("http://foo/")); new URI("http://foo/"));
...@@ -129,7 +133,7 @@ public class FeignLoadBalancerTests { ...@@ -129,7 +133,7 @@ public class FeignLoadBalancerTests {
@SneakyThrows @SneakyThrows
public void testSecureUriFromClientConfigOverride() { public void testSecureUriFromClientConfigOverride() {
this.feignLoadBalancer = new FeignLoadBalancer(this.lb, this.config, this.feignLoadBalancer = new FeignLoadBalancer(this.lb, this.config,
this.inspector); this.inspector, retryTemplate, loadBalancedRetryPolicyFactory);
Server server = Mockito.mock(Server.class); Server server = Mockito.mock(Server.class);
when(server.getPort()).thenReturn(443); when(server.getPort()).thenReturn(443);
when(server.getHost()).thenReturn("foo"); when(server.getHost()).thenReturn("foo");
......
...@@ -16,14 +16,11 @@ ...@@ -16,14 +16,11 @@
package org.springframework.cloud.netflix.feign.ribbon; package org.springframework.cloud.netflix.feign.ribbon;
import static org.junit.Assert.assertEquals; import com.netflix.loadbalancer.Server;
import static org.junit.Assert.assertNotNull; import com.netflix.loadbalancer.ServerList;
import static org.junit.Assert.assertTrue; import lombok.AllArgsConstructor;
import lombok.Data;
import java.lang.reflect.InvocationHandler; import lombok.NoArgsConstructor;
import java.lang.reflect.Proxy;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -44,12 +41,13 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -44,12 +41,13 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.netflix.loadbalancer.Server; import java.lang.reflect.InvocationHandler;
import com.netflix.loadbalancer.ServerList; import java.lang.reflect.Proxy;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.AllArgsConstructor; import static org.junit.Assert.assertEquals;
import lombok.Data; import static org.junit.Assert.assertNotNull;
import lombok.NoArgsConstructor; import static org.junit.Assert.assertTrue;
/** /**
* Tests the Feign Retryer, not ribbon retry. * Tests the Feign Retryer, not ribbon retry.
...@@ -58,7 +56,8 @@ import lombok.NoArgsConstructor; ...@@ -58,7 +56,8 @@ import lombok.NoArgsConstructor;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = FeignRibbonClientRetryTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = { @SpringBootTest(classes = FeignRibbonClientRetryTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
"spring.application.name=feignclientretrytest", "feign.okhttp.enabled=false", "spring.application.name=feignclientretrytest", "feign.okhttp.enabled=false",
"feign.httpclient.enabled=false", "feign.hystrix.enabled=false", }) "feign.httpclient.enabled=false", "feign.hystrix.enabled=false", "localapp.ribbon.MaxAutoRetries=2",
"localapp.ribbon.MaxAutoRetriesNextServer=3"})
@DirtiesContext @DirtiesContext
public class FeignRibbonClientRetryTests { public class FeignRibbonClientRetryTests {
......
...@@ -16,19 +16,6 @@ ...@@ -16,19 +16,6 @@
package org.springframework.cloud.netflix.feign.ribbon; package org.springframework.cloud.netflix.feign.ribbon;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hamcrest.CustomMatcher;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl; import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
...@@ -37,11 +24,24 @@ import com.netflix.loadbalancer.ILoadBalancer; ...@@ -37,11 +24,24 @@ import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.LoadBalancerStats; import com.netflix.loadbalancer.LoadBalancerStats;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerStats; import com.netflix.loadbalancer.ServerStats;
import feign.Client; import feign.Client;
import feign.Request; import feign.Request;
import feign.Request.Options; import feign.Request.Options;
import feign.RequestTemplate; import feign.RequestTemplate;
import org.hamcrest.CustomMatcher;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryPolicyFactory;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.retry.support.RetryTemplate;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/** /**
* @author Dave Syer * @author Dave Syer
...@@ -51,6 +51,7 @@ public class FeignRibbonClientTests { ...@@ -51,6 +51,7 @@ public class FeignRibbonClientTests {
private AbstractLoadBalancer loadBalancer = mock(AbstractLoadBalancer.class); private AbstractLoadBalancer loadBalancer = mock(AbstractLoadBalancer.class);
private Client delegate = mock(Client.class); private Client delegate = mock(Client.class);
private RibbonLoadBalancedRetryPolicyFactory retryPolicyFactory = mock(RibbonLoadBalancedRetryPolicyFactory.class);
private SpringClientFactory factory = new SpringClientFactory() { private SpringClientFactory factory = new SpringClientFactory() {
@Override @Override
...@@ -79,7 +80,8 @@ public class FeignRibbonClientTests { ...@@ -79,7 +80,8 @@ public class FeignRibbonClientTests {
// Even though we don't maintain FeignRibbonClient, keep these tests // Even though we don't maintain FeignRibbonClient, keep these tests
// around to make sure the expected behaviour doesn't break // around to make sure the expected behaviour doesn't break
private Client client = new LoadBalancerFeignClient(this.delegate, new CachingSpringLoadBalancerFactory(this.factory), this.factory); private Client client = new LoadBalancerFeignClient(this.delegate, new CachingSpringLoadBalancerFactory(this.factory,
new RetryTemplate(), retryPolicyFactory), this.factory);
@Before @Before
public void init() { public void init() {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.cloud.netflix.feign.valid; package org.springframework.cloud.netflix.feign.valid;
import org.junit.Test; import org.junit.Test;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.feign.FeignAutoConfiguration; import org.springframework.cloud.netflix.feign.FeignAutoConfiguration;
import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.feign.FeignClient;
...@@ -82,6 +83,7 @@ public class FeignClientValidationTests { ...@@ -82,6 +83,7 @@ public class FeignClientValidationTests {
@Test @Test
public void validLoadBalanced() { public void validLoadBalanced() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
LoadBalancerAutoConfiguration.class,
RibbonAutoConfiguration.class, RibbonAutoConfiguration.class,
FeignRibbonClientAutoConfiguration.class, FeignRibbonClientAutoConfiguration.class,
GoodServiceIdConfiguration.class); GoodServiceIdConfiguration.class);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment