Merge pull request #1612 from spring-cloud/fix-gh-1610

Fixes LoadBalancerFeignClient double loadbalancing
This commit is contained in:
Adrian Cole
2020-04-08 09:27:55 +08:00
committed by GitHub
3 changed files with 44 additions and 31 deletions

View File

@@ -30,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
@@ -67,7 +68,12 @@ public class TraceLoadBalancerFeignClient extends LoadBalancerFeignClient {
Response response = null;
Span fallbackSpan = tracer().nextSpan().start();
try {
response = super.execute(request, options);
if (delegateIsALoadBalancer()) {
response = getDelegate().execute(request, options);
}
else {
response = super.execute(request, options);
}
if (log.isDebugEnabled()) {
log.debug("After receive");
}
@@ -95,6 +101,11 @@ public class TraceLoadBalancerFeignClient extends LoadBalancerFeignClient {
}
}
private boolean delegateIsALoadBalancer() {
return getDelegate() instanceof LoadBalancerFeignClient
|| getDelegate() instanceof FeignBlockingLoadBalancerClient;
}
private Tracer tracer() {
if (this.tracer == null) {
this.tracer = this.beanFactory.getBean(Tracer.class);

View File

@@ -59,10 +59,10 @@ import static org.assertj.core.api.BDDAssertions.then;
public class ManuallyCreatedLoadBalancerFeignClientTests {
@Autowired
MyClient myClient;
MyLoadBalancerClient myLoadBalancerClient;
@Autowired
MyNameRemote myNameRemote;
AnnotatedFeignClient annotatedFeignClient;
@Autowired
ArrayListSpanReporter reporter;
@@ -74,29 +74,29 @@ public class ManuallyCreatedLoadBalancerFeignClientTests {
@Test
public void should_reuse_custom_feign_client() {
String response = this.myNameRemote.get();
String response = this.annotatedFeignClient.get();
then(this.myClient.wasCalled()).isTrue();
then(this.myLoadBalancerClient.wasCalled()).isTrue();
then(response).isEqualTo("foo");
List<Span> spans = this.reporter.getSpans();
// retries
then(spans).hasSize(1);
then(spans.get(0).tags().get("http.path")).isEqualTo("/");
then(spans.get(0).tags().get("http.path")).isEqualTo("/test");
}
@Test
public void my_client_called() {
this.myNameRemote.get();
then(this.myClient.wasCalled()).isTrue();
this.annotatedFeignClient.get();
then(this.myLoadBalancerClient.wasCalled()).isTrue();
}
@Test
public void span_captured() {
this.myNameRemote.get();
this.annotatedFeignClient.get();
List<Span> spans = this.reporter.getSpans();
// retries
then(spans).hasSize(1);
then(spans.get(0).tags().get("http.path")).isEqualTo("/");
then(spans.get(0).tags().get("http.path")).isEqualTo("/test");
}
}
@@ -109,7 +109,8 @@ class Application {
@Bean
public Client client(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new MyClient(new MyDelegateClient(), cachingFactory, clientFactory);
return new MyLoadBalancerClient(new MyDelegateClient(), cachingFactory,
clientFactory);
}
@Bean
@@ -124,9 +125,10 @@ class Application {
}
class MyClient extends LoadBalancerFeignClient {
class MyLoadBalancerClient extends LoadBalancerFeignClient {
MyClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory,
MyLoadBalancerClient(Client delegate,
CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
}
@@ -161,9 +163,9 @@ class MyDelegateClient implements Client {
}
@FeignClient(name = "foo", url = "http://foo")
interface MyNameRemote {
interface AnnotatedFeignClient {
@RequestMapping(value = "/", method = RequestMethod.GET)
@RequestMapping(value = "/test", method = RequestMethod.GET)
String get();
}

View File

@@ -65,13 +65,13 @@ import static org.assertj.core.api.BDDAssertions.then;
public class ManuallyCreatedDelegateLoadBalancerFeignClientTests {
@Autowired
MyClient myClient;
MyLoadBalancerClient myLoadBalancerClient;
@Autowired
MyDelegateClient myDelegateClient;
@Autowired
MyNameRemote myNameRemote;
AnnotatedFeignClient annotatedFeignClient;
@Autowired
ArrayListSpanReporter reporter;
@@ -83,31 +83,31 @@ public class ManuallyCreatedDelegateLoadBalancerFeignClientTests {
@Test
public void should_reuse_custom_feign_client() {
String response = this.myNameRemote.get();
String response = this.annotatedFeignClient.get();
then(this.myClient.wasCalled()).isTrue();
then(this.myLoadBalancerClient.wasCalled()).isTrue();
then(this.myDelegateClient.wasCalled()).isTrue();
then(response).isEqualTo("foo");
List<Span> spans = this.reporter.getSpans();
// retries
then(spans).hasSize(1);
then(spans.get(0).tags().get("http.path")).isEqualTo("/");
then(spans.get(0).tags().get("http.path")).isEqualTo("/test");
}
@Test
public void my_client_called() {
this.myNameRemote.get();
then(this.myClient.wasCalled()).isTrue();
this.annotatedFeignClient.get();
then(this.myLoadBalancerClient.wasCalled()).isTrue();
then(this.myDelegateClient.wasCalled()).isTrue();
}
@Test
public void span_captured() {
this.myNameRemote.get();
this.annotatedFeignClient.get();
List<Span> spans = this.reporter.getSpans();
// retries
then(spans).hasSize(1);
then(spans.get(0).tags().get("http.path")).isEqualTo("/");
then(spans.get(0).tags().get("http.path")).isEqualTo("/test");
}
}
@@ -126,15 +126,15 @@ class Application {
public Client client(MyDelegateClient myDelegateClient,
CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new MyClient(myDelegateClient, cachingFactory, clientFactory);
return new MyLoadBalancerClient(myDelegateClient, cachingFactory, clientFactory);
}
@Bean
public MyNameRemote myNameRemote(Client client, Decoder decoder, Encoder encoder,
public AnnotatedFeignClient annotatedFeignClient(Client client, Decoder decoder, Encoder encoder,
Contract contract) {
return Feign.builder().client(client).encoder(encoder).decoder(decoder)
.contract(contract)
.target(new HardCodedTarget<>(MyNameRemote.class, "foo", "http://foo"));
.target(new HardCodedTarget<>(AnnotatedFeignClient.class, "foo", "http://foo"));
}
@Bean
@@ -149,9 +149,9 @@ class Application {
}
class MyClient extends LoadBalancerFeignClient {
class MyLoadBalancerClient extends LoadBalancerFeignClient {
MyClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory,
MyLoadBalancerClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
}
@@ -190,9 +190,9 @@ class MyDelegateClient implements Client {
}
@FeignClient(name = "foo", url = "http://foo")
interface MyNameRemote {
interface AnnotatedFeignClient {
@RequestMapping(value = "/", method = RequestMethod.GET)
@RequestMapping(value = "/test", method = RequestMethod.GET)
String get();
}