GH-140: Support for Composite Discovery client (#198)
Add support for Composite Discovery client * Test that the default discovery client is present * Return a local Service instance from Composite Discovery Client fixes gh-140
This commit is contained in:
committed by
Spencer Gibb
parent
c953240620
commit
ca06452be0
@@ -0,0 +1,73 @@
|
||||
package org.springframework.cloud.client.discovery.composite;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link DiscoveryClient} composed of other Discovery Client's and will delegate the
|
||||
* calls to each of them in order
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
public class CompositeDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
private final List<DiscoveryClient> discoveryClients;
|
||||
|
||||
public CompositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
|
||||
this.discoveryClients = discoveryClients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Composite Discovery Client";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstance getLocalServiceInstance() {
|
||||
if (this.discoveryClients != null) {
|
||||
for (DiscoveryClient discoveryClient : discoveryClients) {
|
||||
ServiceInstance serviceInstance = discoveryClient.getLocalServiceInstance();
|
||||
if (serviceInstance != null) {
|
||||
return serviceInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String serviceId) {
|
||||
if (this.discoveryClients != null) {
|
||||
for (DiscoveryClient discoveryClient : discoveryClients) {
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
|
||||
if (instances != null && instances.size() > 0) {
|
||||
return instances;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
LinkedHashSet<String> services = new LinkedHashSet<>();
|
||||
if (this.discoveryClients != null) {
|
||||
for (DiscoveryClient discoveryClient : discoveryClients) {
|
||||
List<String> serviceForClient = discoveryClient.getServices();
|
||||
if (serviceForClient != null) {
|
||||
services.addAll(serviceForClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(services);
|
||||
}
|
||||
|
||||
List<DiscoveryClient> getDiscoveryClients() {
|
||||
return discoveryClients;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.springframework.cloud.client.discovery.composite;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Auto-configuration for Composite Discovery Client.
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
|
||||
public class CompositeDiscoveryClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public CompositeDiscoveryClient compositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
|
||||
return new CompositeDiscoveryClient(discoveryClients);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +1,23 @@
|
||||
package org.springframework.cloud.client.discovery.simple;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Spring Boot Auto-Configuration for Simple Properties based Discovery Client
|
||||
*
|
||||
@@ -25,8 +25,6 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(DiscoveryClient.class)
|
||||
@EnableConfigurationProperties
|
||||
@AutoConfigureBefore(NoopDiscoveryClientAutoConfiguration.class)
|
||||
public class SimpleDiscoveryClientAutoConfiguration {
|
||||
|
||||
@@ -54,9 +52,9 @@ public class SimpleDiscoveryClientAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient simpleDiscoveryClient(
|
||||
SimpleDiscoveryProperties simpleDiscoveryProperties) {
|
||||
return new SimpleDiscoveryClient(simpleDiscoveryProperties);
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
public DiscoveryClient simpleDiscoveryClient() {
|
||||
return new SimpleDiscoveryClient(simpleDiscoveryProperties());
|
||||
}
|
||||
|
||||
private int findPort() {
|
||||
|
||||
@@ -7,6 +7,7 @@ org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration
|
||||
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
|
||||
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
|
||||
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
|
||||
org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration,\
|
||||
org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.springframework.cloud.client.discovery.composite;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.discovery.simple.SimpleDiscoveryClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Composite Discovery Client should be the one found by default.
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CompositeDiscoveryClientAutoConfigurationTests {
|
||||
|
||||
@Autowired
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
@Test
|
||||
public void compositeDiscoveryClientShouldBeTheDefault() {
|
||||
assertThat(discoveryClient).isInstanceOf(CompositeDiscoveryClient.class);
|
||||
CompositeDiscoveryClient compositeDiscoveryClient = (CompositeDiscoveryClient) discoveryClient;
|
||||
assertThat(compositeDiscoveryClient.getDiscoveryClients()).hasSize(2);
|
||||
assertThat(compositeDiscoveryClient.getDiscoveryClients().get(0).description())
|
||||
.isEqualTo("A custom discovery client");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleDiscoveryClientShouldBeHaveTheLowestPrecedence() {
|
||||
CompositeDiscoveryClient compositeDiscoveryClient = (CompositeDiscoveryClient) discoveryClient;
|
||||
assertThat(compositeDiscoveryClient.getDiscoveryClients().get(0).description())
|
||||
.isEqualTo("A custom discovery client");
|
||||
assertThat(compositeDiscoveryClient.getDiscoveryClients().get(1))
|
||||
.isInstanceOf(SimpleDiscoveryClient.class);
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
public static class Config {
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient customDiscoveryClient1() {
|
||||
return new DiscoveryClient() {
|
||||
@Override
|
||||
public String description() {
|
||||
return "A custom discovery client";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstance getLocalServiceInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String serviceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package org.springframework.cloud.client.discovery.composite;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for behavior of Composite Discovery Client
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(properties = {
|
||||
"spring.application.name=service0",
|
||||
"spring.cloud.discovery.client.simple.instances.service1[0].uri=http://s1-1:8080",
|
||||
"spring.cloud.discovery.client.simple.instances.service1[1].uri=https://s1-2:8443",
|
||||
"spring.cloud.discovery.client.simple.instances.service2[0].uri=https://s2-1:8080",
|
||||
"spring.cloud.discovery.client.simple.instances.service2[1].uri=https://s2-2:443" })
|
||||
public class CompositeDiscoveryClientTests {
|
||||
|
||||
@Autowired
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
@Test
|
||||
public void getInstancesByServiceIdShouldDelegateCall() {
|
||||
assertThat(this.discoveryClient).isInstanceOf(CompositeDiscoveryClient.class);
|
||||
|
||||
assertThat(this.discoveryClient.getInstances("service1")).hasSize(2);
|
||||
|
||||
ServiceInstance s1 = this.discoveryClient.getInstances("service1").get(0);
|
||||
assertThat(s1.getHost()).isEqualTo("s1-1");
|
||||
assertThat(s1.getPort()).isEqualTo(8080);
|
||||
assertThat(s1.getUri()).isEqualTo(URI.create("http://s1-1:8080"));
|
||||
assertThat(s1.isSecure()).isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServicesShouldAggregateAllServiceNames() {
|
||||
assertThat(this.discoveryClient.getServices()).containsOnlyOnce("service1", "service2", "custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDescriptionShouldBeComposite() {
|
||||
assertThat(this.discoveryClient.description()).isEqualTo("Composite Discovery Client");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstancesShouldRespectOrder() {
|
||||
assertThat(this.discoveryClient.getInstances("custom")).hasSize(1);
|
||||
assertThat(this.discoveryClient.getInstances("custom")).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstancesByUnknownServiceIdShouldReturnAnEmptyList() {
|
||||
assertThat(this.discoveryClient.getInstances("unknown")).hasSize(0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void localServiceInstanceShouldReturnTheFirstMatch() {
|
||||
assertThat(this.discoveryClient.getLocalServiceInstance().getServiceId()).isEqualTo("service0");
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
public static class Config {
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
public DiscoveryClient customDiscoveryClient() {
|
||||
return new DiscoveryClient() {
|
||||
@Override
|
||||
public String description() {
|
||||
return "A custom discovery client";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstance getLocalServiceInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String serviceId) {
|
||||
if (serviceId.equals("custom")) {
|
||||
ServiceInstance s1 = new DefaultServiceInstance("custom", "host",
|
||||
123, false);
|
||||
return Arrays.asList(s1);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
return Arrays.asList("custom");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,36 +3,34 @@ package org.springframework.cloud.client.discovery.simple;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* DiscoveryClient implementation defaults to {@link SimpleDiscoveryClient}
|
||||
* DiscoveryClient implementation defaults to {@link CompositeDiscoveryClient}
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = DiscoveryClientAutoConfigurationDefaultTests.App.class)
|
||||
@SpringBootTest(classes = DiscoveryClientAutoConfigurationDefaultTests.Config.class)
|
||||
public class DiscoveryClientAutoConfigurationDefaultTests {
|
||||
|
||||
@Autowired
|
||||
DiscoveryClient discoveryClient;
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
@Test
|
||||
public void simpleDiscoveryClientShouldBeTheDefault() {
|
||||
assertThat(discoveryClient).isInstanceOf(SimpleDiscoveryClient.class);
|
||||
assertThat(discoveryClient).isInstanceOf(CompositeDiscoveryClient.class);
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
public static class App {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(App.class, args);
|
||||
}
|
||||
public static class Config {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@@ -32,7 +31,7 @@ public class SimpleDiscoveryClientPropertiesMappingTests {
|
||||
private SimpleDiscoveryProperties props;
|
||||
|
||||
@Autowired
|
||||
private DiscoveryClient discoveryClient;
|
||||
private SimpleDiscoveryClient discoveryClient;
|
||||
|
||||
@Test
|
||||
public void propsShouldGetCleanlyMapped() {
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
package org.springframework.cloud.client.discovery.simple;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
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.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = UserDefinedDiscoveryClientOverridesDefaultsTests.App.class)
|
||||
public class UserDefinedDiscoveryClientOverridesDefaultsTests {
|
||||
|
||||
@Autowired
|
||||
DiscoveryClient discoveryClient;
|
||||
|
||||
@Test
|
||||
public void testDiscoveryClientIsNotNoop() {
|
||||
assertThat(discoveryClient).isNotInstanceOf(SimpleDiscoveryClient.class);
|
||||
|
||||
assertThat(discoveryClient.description())
|
||||
.isEqualTo("user defined discovery client");
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
public static class App {
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient discoveryClient() {
|
||||
return new DiscoveryClient() {
|
||||
@Override
|
||||
public String description() {
|
||||
return "user defined discovery client";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstance getLocalServiceInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String serviceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(App.class, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user