Added an interface to provide your own load balancing strategy for Zipkin (#743)
Added an interface to provide your own load balancing strategy for Zipkin. The load balancing strategy allows usage of LoadBalancerClient (impl of which can be Ribbon) fixes #734
This commit is contained in:
committed by
GitHub
parent
9b42dff6c5
commit
07ea07e2b6
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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<ServiceInstance> 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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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<ServiceInstance> 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<String, String> getMetadata() {
|
||||
@Bean LoadBalancerClient loadBalancerClient() {
|
||||
return new LoadBalancerClient() {
|
||||
@Override public <T> T execute(String serviceId,
|
||||
LoadBalancerRequest<T> request) throws IOException {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@Override public <T> T execute(String serviceId,
|
||||
ServiceInstance serviceInstance, LoadBalancerRequest<T> 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<String, String> getMetadata() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
return Collections.singletonList("zipkin");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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<ServiceInstance> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<ServiceInstance> 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<String, String> getMetadata() {
|
||||
@Bean LoadBalancerClient loadBalancerClient() {
|
||||
return new LoadBalancerClient() {
|
||||
@Override public <T> T execute(String serviceId,
|
||||
LoadBalancerRequest<T> request) throws IOException {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@Override public <T> T execute(String serviceId,
|
||||
ServiceInstance serviceInstance, LoadBalancerRequest<T> 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<String, String> getMetadata() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
return Collections.singletonList("zipkin");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user