Merge pull request #412 from OlgaMaciaszek/gh-304-add-discovery-clients-order-support
Gh 304 add discovery clients order support
This commit is contained in:
@@ -254,6 +254,17 @@ To disable it, set `spring.cloud.discovery.client.health-indicator.enabled=false
|
||||
To disable the description field of the `DiscoveryClientHealthIndicator`, set `spring.cloud.discovery.client.health-indicator.include-description=false`.
|
||||
Otherwise, it can bubble up as the `description` of the rolled up `HealthIndicator`.
|
||||
|
||||
==== Ordering `DiscoveryClient` instances
|
||||
`DiscoveryClient` interface extends `Ordered`. This is useful when using multiple discovery
|
||||
clients, as it allows you to define the order of the returned discovery clients, similar to
|
||||
how you can order the beans loaded by a Spring application. By default, the order of any `DiscoveryClient` is set to
|
||||
`0`. If you want to set a different order for your custom `DiscoveryClient` implementations, you just need to override
|
||||
the `getOrder()` method so that it returns the value that is suitable for your setup. Apart from this, you can use
|
||||
properties to set the order of the `DiscoveryClient`
|
||||
implementations provided by Spring Cloud, among others `ConsulDiscoveryClient`, `EurekaDiscoveryClient` and
|
||||
`ZookeeperDiscoveryClient`. In order to do it, you just need to set the
|
||||
`spring.cloud.{clientIdentifier}.discovery.order` (or `eureka.client.order` for Eureka) property to the desired value.
|
||||
|
||||
=== ServiceRegistry
|
||||
|
||||
Commons now provides a `ServiceRegistry` interface that provides methods such as `register(Registration)` and `deregister(Registration)`, which let you provide custom registered services.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,22 +19,29 @@ package org.springframework.cloud.client.discovery;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Represents read operations commonly available to discovery services such as Netflix
|
||||
* Eureka or consul.io.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public interface DiscoveryClient {
|
||||
public interface DiscoveryClient extends Ordered {
|
||||
|
||||
int DEFAULT_ORDER = 0;
|
||||
|
||||
/**
|
||||
* A human-readable description of the implementation, used in HealthIndicator.
|
||||
*
|
||||
* @return The description.
|
||||
*/
|
||||
String description();
|
||||
|
||||
/**
|
||||
* Gets all ServiceInstances associated with a particular serviceId.
|
||||
*
|
||||
* @param serviceId The serviceId to query.
|
||||
* @return A List of ServiceInstance.
|
||||
*/
|
||||
@@ -45,4 +52,13 @@ public interface DiscoveryClient {
|
||||
*/
|
||||
List<String> getServices();
|
||||
|
||||
/**
|
||||
* Default implementation for getting order of discovery clients.
|
||||
*
|
||||
* @return order
|
||||
*/
|
||||
@Override
|
||||
default int getOrder() {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.discovery.composite;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -7,18 +23,21 @@ import java.util.List;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
|
||||
/**
|
||||
* A {@link DiscoveryClient} that is composed of other discovery clients and delegates
|
||||
* calls to each of them in order.
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class CompositeDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
private final List<DiscoveryClient> discoveryClients;
|
||||
|
||||
public CompositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
|
||||
AnnotationAwareOrderComparator.sort(discoveryClients);
|
||||
this.discoveryClients = discoveryClients;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.discovery.simple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -12,6 +28,7 @@ import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperti
|
||||
* properties file as a source of service instances.
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class SimpleDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
@@ -42,4 +59,9 @@ public class SimpleDiscoveryClient implements DiscoveryClient {
|
||||
public List<String> getServices() {
|
||||
return new ArrayList<>(this.simpleDiscoveryProperties.getInstances().keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.simpleDiscoveryProperties.getOrder();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.discovery.simple;
|
||||
|
||||
import java.net.URI;
|
||||
@@ -10,13 +26,18 @@ import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
|
||||
/**
|
||||
* Properties to hold the details of a
|
||||
* {@link org.springframework.cloud.client.discovery.DiscoveryClient} service instances
|
||||
* for a given service.
|
||||
* It also holds the user-configurable order that will be used to establish the
|
||||
* precedence of this client in the list of clients
|
||||
* used by {@link org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient}.
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
|
||||
@ConfigurationProperties(prefix = "spring.cloud.discovery.client.simple")
|
||||
@@ -30,6 +51,8 @@ public class SimpleDiscoveryProperties {
|
||||
*/
|
||||
private SimpleServiceInstance local = new SimpleServiceInstance();
|
||||
|
||||
private int order = DiscoveryClient.DEFAULT_ORDER;
|
||||
|
||||
public Map<String, List<SimpleServiceInstance>> getInstances() {
|
||||
return this.instances;
|
||||
}
|
||||
@@ -42,6 +65,14 @@ public class SimpleDiscoveryProperties {
|
||||
return this.local;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
for (String key : this.instances.keySet()) {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.discovery.composite;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientTestsConfig.CUSTOM_DISCOVERY_CLIENT;
|
||||
import static org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientTestsConfig.CUSTOM_SERVICE_ID;
|
||||
import static org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientTestsConfig.DEFAULT_ORDER_DISCOVERY_CLIENT;
|
||||
import static org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientTestsConfig.FOURTH_DISCOVERY_CLIENT;
|
||||
|
||||
/**
|
||||
* Tests for the support of ordered {@link DiscoveryClient} instances in {@link CompositeDiscoveryClient}
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(properties = "spring.cloud.discovery.client.simple.order:2", classes = {
|
||||
CompositeDiscoveryClientTestsConfig.class})
|
||||
public class CompositeDiscoveryClientOrderTest {
|
||||
|
||||
@Autowired
|
||||
DiscoveryClient discoveryClient;
|
||||
|
||||
@Test
|
||||
public void shouldGetOrderedDiscoveryClients() {
|
||||
// when:
|
||||
List<DiscoveryClient> discoveryClients = ((CompositeDiscoveryClient) this.discoveryClient)
|
||||
.getDiscoveryClients();
|
||||
|
||||
// then:
|
||||
assertThat(discoveryClients.get(0).description())
|
||||
.isEqualTo(CUSTOM_DISCOVERY_CLIENT);
|
||||
assertThat(discoveryClients.get(1).description())
|
||||
.isEqualTo(DEFAULT_ORDER_DISCOVERY_CLIENT);
|
||||
assertThat(discoveryClients.get(2).description())
|
||||
.isEqualTo("Simple Discovery Client");
|
||||
assertThat(discoveryClients.get(3).description())
|
||||
.isEqualTo(FOURTH_DISCOVERY_CLIENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOnlyReturnServiceInstancesForTheHighestPrecedenceDiscoveryClient() {
|
||||
// when:
|
||||
List<ServiceInstance> serviceInstances = this.discoveryClient
|
||||
.getInstances(CUSTOM_SERVICE_ID);
|
||||
|
||||
// then:
|
||||
assertThat(serviceInstances).hasSize(1);
|
||||
assertThat(serviceInstances.get(0).getPort()).isEqualTo(123);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,38 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.discovery.composite;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
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 static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientTestsConfig.CUSTOM_SERVICE_ID;
|
||||
|
||||
/**
|
||||
* Tests for behavior of Composite Discovery Client
|
||||
*
|
||||
*
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
|
||||
@@ -32,7 +42,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
"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" })
|
||||
"spring.cloud.discovery.client.simple.instances.service2[1].uri=https://s2-2:443",}, classes = {
|
||||
CompositeDiscoveryClientTestsConfig.class})
|
||||
public class CompositeDiscoveryClientTests {
|
||||
|
||||
@Autowired
|
||||
@@ -50,56 +61,25 @@ public class CompositeDiscoveryClientTests {
|
||||
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);
|
||||
assertThat(this.discoveryClient.getInstances(CUSTOM_SERVICE_ID)).hasSize(1);
|
||||
assertThat(this.discoveryClient.getInstances(CUSTOM_SERVICE_ID)).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstancesByUnknownServiceIdShouldReturnAnEmptyList() {
|
||||
assertThat(this.discoveryClient.getInstances("unknown")).hasSize(0);
|
||||
}
|
||||
|
||||
@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 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");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.discovery.composite;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
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 static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* Test configuration for {@link CompositeDiscoveryClient} tests.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
public class CompositeDiscoveryClientTestsConfig {
|
||||
|
||||
static final String DEFAULT_ORDER_DISCOVERY_CLIENT = "Default order discovery client";
|
||||
static final String CUSTOM_DISCOVERY_CLIENT = "A custom discovery client";
|
||||
static final String FOURTH_DISCOVERY_CLIENT = "Fourth discovery client";
|
||||
static final String CUSTOM_SERVICE_ID = "custom";
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient customDiscoveryClient() {
|
||||
return aDiscoveryClient(-1, CUSTOM_DISCOVERY_CLIENT);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient thirdOrderCustomDiscoveryClient() {
|
||||
return aDiscoveryClient(3, FOURTH_DISCOVERY_CLIENT);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient defaultOrderDiscoveryClient() {
|
||||
return aDiscoveryClient(null, DEFAULT_ORDER_DISCOVERY_CLIENT);
|
||||
}
|
||||
|
||||
private DiscoveryClient aDiscoveryClient(Integer order, String description) {
|
||||
return new DiscoveryClient() {
|
||||
@Override
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String serviceId) {
|
||||
if (serviceId.equals(CUSTOM_SERVICE_ID)) {
|
||||
ServiceInstance s1 = new DefaultServiceInstance(CUSTOM_SERVICE_ID,
|
||||
"host", 123, false);
|
||||
return singletonList(s1);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
return singletonList(CUSTOM_SERVICE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return order != null ? order : DiscoveryClient.super.getOrder();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user