diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/LoadBalancerClientZipkinLoadBalancer.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/LoadBalancerClientZipkinLoadBalancer.java new file mode 100644 index 000000000..fa9d68c43 --- /dev/null +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/LoadBalancerClientZipkinLoadBalancer.java @@ -0,0 +1,31 @@ +package org.springframework.cloud.sleuth.zipkin; + +import java.net.URI; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; + +class LoadBalancerClientZipkinLoadBalancer implements ZipkinLoadBalancer { + + private final LoadBalancerClient loadBalancerClient; + private final ZipkinProperties zipkinProperties; + + LoadBalancerClientZipkinLoadBalancer(LoadBalancerClient loadBalancerClient, + ZipkinProperties zipkinProperties) { + this.loadBalancerClient = loadBalancerClient; + this.zipkinProperties = zipkinProperties; + } + + @Override + public URI instance() { + if (this.loadBalancerClient != null) { + URI uri = URI.create(this.zipkinProperties.getBaseUrl()); + String host = uri.getHost(); + ServiceInstance instance = this.loadBalancerClient.choose(host); + if (instance != null) { + return URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort())); + } + } + return URI.create(this.zipkinProperties.getBaseUrl()); + } +} \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinAutoConfiguration.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinAutoConfiguration.java index 272d58b29..bbcd9160c 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinAutoConfiguration.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinAutoConfiguration.java @@ -31,8 +31,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClas import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.commons.util.InetUtils; import org.springframework.cloud.context.config.annotation.RefreshScope; @@ -92,43 +92,41 @@ public class ZipkinAutoConfiguration { } @Configuration - @ConditionalOnClass(DiscoveryClient.class) + @ConditionalOnClass(LoadBalancerClient.class) static class DiscoveryClientZipkinUrlExtractorConfiguration { - @Autowired(required = false) DiscoveryClient discoveryClient; + @Autowired(required = false) LoadBalancerClient client; @Bean - ZipkinUrlExtractor zipkinUrlExtractor() { - final DiscoveryClient discoveryClient = this.discoveryClient; - return new ZipkinUrlExtractor() { - @Override - public URI zipkinUrl(ZipkinProperties zipkinProperties) { - if (discoveryClient != null) { - URI uri = URI.create(zipkinProperties.getBaseUrl()); - String host = uri.getHost(); - List instances = discoveryClient.getInstances(host); - if (!instances.isEmpty()) { - return instances.get(0).getUri(); - } - } + @ConditionalOnMissingBean + ZipkinLoadBalancer loadBalancerClientZipkinLoadBalancer(ZipkinProperties zipkinProperties) { + return new LoadBalancerClientZipkinLoadBalancer(this.client, zipkinProperties); + } + } + + @Configuration + @ConditionalOnMissingClass("org.springframework.cloud.client.loadbalancer.LoadBalancerClient") + static class DefaultZipkinUrlExtractorConfiguration { + + @Bean + @ConditionalOnMissingBean + ZipkinLoadBalancer loadBalancerClientZipkinLoadBalancer(final ZipkinProperties zipkinProperties) { + return new ZipkinLoadBalancer() { + @Override public URI instance() { return URI.create(zipkinProperties.getBaseUrl()); } }; } } - @Configuration - @ConditionalOnMissingClass("org.springframework.cloud.client.discovery.DiscoveryClient") - static class DefaultZipkinUrlExtractorConfiguration { - @Bean - ZipkinUrlExtractor zipkinUrlExtractor() { - return new ZipkinUrlExtractor() { - @Override - public URI zipkinUrl(ZipkinProperties zipkinProperties) { - return URI.create(zipkinProperties.getBaseUrl()); - } - }; - } + @Bean + ZipkinUrlExtractor zipkinUrlExtractor(final ZipkinLoadBalancer zipkinLoadBalancer) { + return new ZipkinUrlExtractor() { + @Override + public URI zipkinUrl(ZipkinProperties zipkinProperties) { + return zipkinLoadBalancer.instance(); + } + }; } @Bean diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinLoadBalancer.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinLoadBalancer.java new file mode 100644 index 000000000..83b2af371 --- /dev/null +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinLoadBalancer.java @@ -0,0 +1,19 @@ +package org.springframework.cloud.sleuth.zipkin; + +import java.net.URI; + +/** + * Load balancing strategy for picking a Zipkin instance + * + * @author Marcin Grzejszczak + * @since 1.3.0 + */ +public interface ZipkinLoadBalancer { + + /** + * Returns a concrete {@link URI} of a Zipkin instance. + * + * @return {@link URI} of the picked instance + */ + URI instance(); +} diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinDiscoveryClientTests.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinDiscoveryClientTests.java index 80027526c..1480a7d9f 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinDiscoveryClientTests.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinDiscoveryClientTests.java @@ -9,11 +9,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import org.assertj.core.api.BDDAssertions; import org.awaitility.Awaitility; -import org.junit.Before; import org.junit.ClassRule; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -21,12 +18,13 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.SpanReporter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.SocketUtils; import zipkin.junit.ZipkinRule; @@ -52,67 +50,59 @@ public class ZipkinDiscoveryClientTests { @Configuration @EnableAutoConfiguration static class Config { - @Bean - DiscoveryClient client() { - return new ZipkinDiscoveryClient(); - } - } -} - -class ZipkinDiscoveryClient implements DiscoveryClient { - - @Override - public String description() { - return ""; - } - - @Override - public ServiceInstance getLocalServiceInstance() { - return null; - } - - @Override - public List getInstances(String s) { - if ("zipkin".equals(s)) { - return Collections.singletonList(new ServiceInstance() { - @Override - public String getServiceId() { - return "zipkin"; - } - - @Override - public String getHost() { - return "localhost"; - } - - @Override - public int getPort() { - return URI.create(ZIPKIN_RULE.httpUrl()).getPort(); - } - - @Override - public boolean isSecure() { - return false; - } - - @Override - public URI getUri() { - return URI.create(ZIPKIN_RULE.httpUrl()); - } - - @Override - public Map getMetadata() { + @Bean LoadBalancerClient loadBalancerClient() { + return new LoadBalancerClient() { + @Override public T execute(String serviceId, + LoadBalancerRequest request) throws IOException { return null; } - }); + + @Override public T execute(String serviceId, + ServiceInstance serviceInstance, LoadBalancerRequest request) + throws IOException { + return null; + } + + @Override public URI reconstructURI(ServiceInstance instance, + URI original) { + return null; + } + + @Override public ServiceInstance choose(String serviceId) { + return new ServiceInstance() { + @Override + public String getServiceId() { + return "zipkin"; + } + + @Override + public String getHost() { + return "localhost"; + } + + @Override + public int getPort() { + return URI.create(ZIPKIN_RULE.httpUrl()).getPort(); + } + + @Override + public boolean isSecure() { + return false; + } + + @Override + public URI getUri() { + return URI.create(ZIPKIN_RULE.httpUrl()); + } + + @Override + public Map getMetadata() { + return null; + } + }; + } + }; } - return Collections.emptyList(); } - - @Override - public List getServices() { - return Collections.singletonList("zipkin"); - } - } \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinLoadBalancer.java b/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinLoadBalancer.java new file mode 100644 index 000000000..c3408dfb7 --- /dev/null +++ b/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinLoadBalancer.java @@ -0,0 +1,19 @@ +package org.springframework.cloud.sleuth.zipkin2; + +import java.net.URI; + +/** + * Load balancing strategy for picking a Zipkin instance + * + * @author Marcin Grzejszczak + * @since 1.3.0 + */ +public interface ZipkinLoadBalancer { + + /** + * Returns a concrete {@link URI} of a Zipkin instance. + * + * @return {@link URI} of the picked instance + */ + URI instance(); +} diff --git a/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/LoadBalancerClientZipkinLoadBalancer.java b/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/LoadBalancerClientZipkinLoadBalancer.java new file mode 100644 index 000000000..9ef97f125 --- /dev/null +++ b/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/LoadBalancerClientZipkinLoadBalancer.java @@ -0,0 +1,33 @@ +package org.springframework.cloud.sleuth.zipkin2.sender; + +import java.net.URI; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.sleuth.zipkin2.ZipkinLoadBalancer; +import org.springframework.cloud.sleuth.zipkin2.ZipkinProperties; + +class LoadBalancerClientZipkinLoadBalancer implements ZipkinLoadBalancer { + + private final LoadBalancerClient loadBalancerClient; + private final ZipkinProperties zipkinProperties; + + LoadBalancerClientZipkinLoadBalancer(LoadBalancerClient loadBalancerClient, + ZipkinProperties zipkinProperties) { + this.loadBalancerClient = loadBalancerClient; + this.zipkinProperties = zipkinProperties; + } + + @Override + public URI instance() { + if (this.loadBalancerClient != null) { + URI uri = URI.create(this.zipkinProperties.getBaseUrl()); + String host = uri.getHost(); + ServiceInstance instance = this.loadBalancerClient.choose(host); + if (instance != null) { + return URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort())); + } + } + return URI.create(this.zipkinProperties.getBaseUrl()); + } +} \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java b/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java index 60d299d5a..abaceae42 100644 --- a/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java +++ b/spring-cloud-sleuth-zipkin2/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java @@ -2,15 +2,15 @@ package org.springframework.cloud.sleuth.zipkin2.sender; import java.net.URI; import java.net.URISyntaxException; -import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.sleuth.zipkin2.ZipkinLoadBalancer; import org.springframework.cloud.sleuth.zipkin2.ZipkinProperties; import org.springframework.cloud.sleuth.zipkin2.ZipkinRestTemplateCustomizer; import org.springframework.context.annotation.Bean; @@ -39,13 +39,15 @@ class ZipkinRestTemplateSenderConfiguration { } @Configuration - @ConditionalOnMissingClass("org.springframework.cloud.client.discovery.DiscoveryClient") + @ConditionalOnMissingClass("org.springframework.cloud.client.loadbalancer.LoadBalancerClient") static class DefaultZipkinUrlExtractorConfiguration { + @Autowired(required = false) LoadBalancerClient client; + @Bean - ZipkinUrlExtractor zipkinUrlExtractor() { - return new ZipkinUrlExtractor() { - @Override - public URI zipkinUrl(ZipkinProperties zipkinProperties) { + @ConditionalOnMissingBean + ZipkinLoadBalancer noOpLoadBalancer(final ZipkinProperties zipkinProperties) { + return new ZipkinLoadBalancer() { + @Override public URI instance() { return URI.create(zipkinProperties.getBaseUrl()); } }; @@ -53,30 +55,27 @@ class ZipkinRestTemplateSenderConfiguration { } @Configuration - @ConditionalOnClass(DiscoveryClient.class) + @ConditionalOnClass(LoadBalancerClient.class) static class DiscoveryClientZipkinUrlExtractorConfiguration { - @Autowired(required = false) DiscoveryClient discoveryClient; + @Autowired(required = false) LoadBalancerClient client; @Bean - ZipkinUrlExtractor zipkinUrlExtractor() { - final DiscoveryClient discoveryClient = this.discoveryClient; - return new ZipkinUrlExtractor() { - @Override - public URI zipkinUrl(ZipkinProperties zipkinProperties) { - if (discoveryClient != null) { - URI uri = URI.create(zipkinProperties.getBaseUrl()); - String host = uri.getHost(); - List instances = discoveryClient.getInstances(host); - if (!instances.isEmpty()) { - return instances.get(0).getUri(); - } - } - return URI.create(zipkinProperties.getBaseUrl()); - } - }; + @ConditionalOnMissingBean + ZipkinLoadBalancer loadBalancerClientZipkinLoadBalancer(ZipkinProperties zipkinProperties) { + return new LoadBalancerClientZipkinLoadBalancer(this.client, zipkinProperties); } } + + @Bean + ZipkinUrlExtractor zipkinUrlExtractor(final ZipkinLoadBalancer zipkinLoadBalancer) { + return new ZipkinUrlExtractor() { + @Override + public URI zipkinUrl(ZipkinProperties zipkinProperties) { + return zipkinLoadBalancer.instance(); + } + }; + } } /** diff --git a/spring-cloud-sleuth-zipkin2/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java b/spring-cloud-sleuth-zipkin2/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java index 8dd988b9d..9749e6929 100644 --- a/spring-cloud-sleuth-zipkin2/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java +++ b/spring-cloud-sleuth-zipkin2/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java @@ -3,6 +3,7 @@ package org.springframework.cloud.sleuth.zipkin2; import static org.assertj.core.api.BDDAssertions.then; import static org.springframework.cloud.sleuth.zipkin2.ZipkinDiscoveryClientTests.ZIPKIN_RULE; +import java.io.IOException; import java.net.URI; import java.util.Collections; import java.util.List; @@ -17,6 +18,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.SpanReporter; import org.springframework.context.annotation.Bean; @@ -49,67 +52,59 @@ public class ZipkinDiscoveryClientTests { @Configuration @EnableAutoConfiguration static class Config { - @Bean - DiscoveryClient client() { - return new ZipkinDiscoveryClient(); - } - } -} - -class ZipkinDiscoveryClient implements DiscoveryClient { - - @Override - public String description() { - return ""; - } - - @Override - public ServiceInstance getLocalServiceInstance() { - return null; - } - - @Override - public List getInstances(String s) { - if ("zipkin".equals(s)) { - return Collections.singletonList(new ServiceInstance() { - @Override - public String getServiceId() { - return "zipkin"; - } - - @Override - public String getHost() { - return "localhost"; - } - - @Override - public int getPort() { - return URI.create(ZIPKIN_RULE.httpUrl()).getPort(); - } - - @Override - public boolean isSecure() { - return false; - } - - @Override - public URI getUri() { - return URI.create(ZIPKIN_RULE.httpUrl()); - } - - @Override - public Map getMetadata() { + @Bean LoadBalancerClient loadBalancerClient() { + return new LoadBalancerClient() { + @Override public T execute(String serviceId, + LoadBalancerRequest request) throws IOException { return null; } - }); + + @Override public T execute(String serviceId, + ServiceInstance serviceInstance, LoadBalancerRequest request) + throws IOException { + return null; + } + + @Override public URI reconstructURI(ServiceInstance instance, + URI original) { + return null; + } + + @Override public ServiceInstance choose(String serviceId) { + return new ServiceInstance() { + @Override + public String getServiceId() { + return "zipkin"; + } + + @Override + public String getHost() { + return "localhost"; + } + + @Override + public int getPort() { + return URI.create(ZIPKIN_RULE.httpUrl()).getPort(); + } + + @Override + public boolean isSecure() { + return false; + } + + @Override + public URI getUri() { + return URI.create(ZIPKIN_RULE.httpUrl()); + } + + @Override + public Map getMetadata() { + return null; + } + }; + } + }; } - return Collections.emptyList(); } - - @Override - public List getServices() { - return Collections.singletonList("zipkin"); - } - } \ No newline at end of file