Use reactive discovery client for DiscoveryClientRouteDefinitionLocator
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.gateway.discovery;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -27,6 +28,7 @@ import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.gateway.filter.FilterDefinition;
|
||||
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
@@ -49,23 +51,45 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
|
||||
private static final Log log = LogFactory
|
||||
.getLog(DiscoveryClientRouteDefinitionLocator.class);
|
||||
|
||||
private final DiscoveryClient discoveryClient;
|
||||
|
||||
private final DiscoveryLocatorProperties properties;
|
||||
|
||||
private final String routeIdPrefix;
|
||||
|
||||
private final SimpleEvaluationContext evalCtxt;
|
||||
|
||||
private Flux<List<ServiceInstance>> serviceInstances;
|
||||
|
||||
/**
|
||||
* Kept for backwards compatibility. You should use the reactive discovery client.
|
||||
* @param discoveryClient the blocking discovery client
|
||||
* @param properties the configuration properties
|
||||
* @deprecated kept for backwards compatibility
|
||||
*/
|
||||
@Deprecated
|
||||
public DiscoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient,
|
||||
DiscoveryLocatorProperties properties) {
|
||||
this.discoveryClient = discoveryClient;
|
||||
this(discoveryClient.getClass().getSimpleName(), properties);
|
||||
serviceInstances = Flux
|
||||
.defer(() -> Flux.fromIterable(discoveryClient.getServices()))
|
||||
.map(discoveryClient::getInstances)
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
}
|
||||
|
||||
public DiscoveryClientRouteDefinitionLocator(ReactiveDiscoveryClient discoveryClient,
|
||||
DiscoveryLocatorProperties properties) {
|
||||
this(discoveryClient.getClass().getSimpleName(), properties);
|
||||
serviceInstances = discoveryClient.getServices()
|
||||
.flatMap(service -> discoveryClient.getInstances(service).collectList());
|
||||
}
|
||||
|
||||
private DiscoveryClientRouteDefinitionLocator(String discoveryClientName,
|
||||
DiscoveryLocatorProperties properties) {
|
||||
this.properties = properties;
|
||||
if (StringUtils.hasText(properties.getRouteIdPrefix())) {
|
||||
this.routeIdPrefix = properties.getRouteIdPrefix();
|
||||
routeIdPrefix = properties.getRouteIdPrefix();
|
||||
}
|
||||
else {
|
||||
this.routeIdPrefix = this.discoveryClient.getClass().getSimpleName() + "_";
|
||||
routeIdPrefix = discoveryClientName + "_";
|
||||
}
|
||||
evalCtxt = SimpleEvaluationContext.forReadOnlyDataBinding().withInstanceMethods()
|
||||
.build();
|
||||
@@ -94,9 +118,7 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
|
||||
};
|
||||
}
|
||||
|
||||
return Flux.defer(() -> Flux.fromIterable(discoveryClient.getServices()))
|
||||
.subscribeOn(Schedulers.elastic()).map(discoveryClient::getInstances)
|
||||
.filter(instances -> !instances.isEmpty())
|
||||
return serviceInstances.filter(instances -> !instances.isEmpty())
|
||||
.map(instances -> instances.get(0)).filter(includePredicate)
|
||||
.map(instance -> {
|
||||
String serviceId = instance.getServiceId();
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration;
|
||||
import org.springframework.cloud.gateway.config.GatewayAutoConfiguration;
|
||||
import org.springframework.cloud.gateway.filter.FilterDefinition;
|
||||
@@ -49,7 +49,7 @@ import static org.springframework.cloud.gateway.support.NameUtils.normalizeRoute
|
||||
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
|
||||
@AutoConfigureBefore(GatewayAutoConfiguration.class)
|
||||
@AutoConfigureAfter(CompositeDiscoveryClientAutoConfiguration.class)
|
||||
@ConditionalOnClass({ DispatcherHandler.class, DiscoveryClient.class })
|
||||
@ConditionalOnClass({ DispatcherHandler.class, ReactiveDiscoveryClient.class })
|
||||
@EnableConfigurationProperties
|
||||
public class GatewayDiscoveryClientAutoConfiguration {
|
||||
|
||||
@@ -81,10 +81,11 @@ public class GatewayDiscoveryClientAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(DiscoveryClient.class)
|
||||
@ConditionalOnBean(ReactiveDiscoveryClient.class)
|
||||
@ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled")
|
||||
public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(
|
||||
DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
|
||||
ReactiveDiscoveryClient discoveryClient,
|
||||
DiscoveryLocatorProperties properties) {
|
||||
return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
|
||||
package org.springframework.cloud.gateway.discovery;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
@@ -30,7 +29,7 @@ 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.cloud.client.discovery.ReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
|
||||
import org.springframework.cloud.gateway.route.Route;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
@@ -84,7 +83,7 @@ public class DiscoveryClientRouteDefinitionLocatorIntegrationTests {
|
||||
|
||||
}
|
||||
|
||||
private static class TestDiscoveryClient implements DiscoveryClient {
|
||||
private static class TestDiscoveryClient implements ReactiveDiscoveryClient {
|
||||
|
||||
AtomicBoolean single = new AtomicBoolean(true);
|
||||
|
||||
@@ -104,22 +103,22 @@ public class DiscoveryClientRouteDefinitionLocatorIntegrationTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String serviceId) {
|
||||
public Flux<ServiceInstance> getInstances(String serviceId) {
|
||||
if (serviceId.equals("service1")) {
|
||||
return Collections.singletonList(instance1);
|
||||
return Flux.just(instance1);
|
||||
}
|
||||
if (serviceId.equals("service2")) {
|
||||
return Collections.singletonList(instance2);
|
||||
return Flux.just(instance2);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
return Flux.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
public Flux<String> getServices() {
|
||||
if (single.get()) {
|
||||
return Collections.singletonList("service1");
|
||||
return Flux.just("service1");
|
||||
}
|
||||
return Arrays.asList("service1", "service2");
|
||||
return Flux.just("service1", "service2");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,20 +16,20 @@
|
||||
|
||||
package org.springframework.cloud.gateway.discovery;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.gateway.filter.FilterDefinition;
|
||||
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
@@ -95,22 +95,22 @@ public class DiscoveryClientRouteDefinitionLocatorTests {
|
||||
protected static class Config {
|
||||
|
||||
@Bean
|
||||
DiscoveryClient discoveryClient() {
|
||||
DiscoveryClient discoveryClient = mock(DiscoveryClient.class);
|
||||
ReactiveDiscoveryClient discoveryClient() {
|
||||
ReactiveDiscoveryClient discoveryClient = mock(ReactiveDiscoveryClient.class);
|
||||
when(discoveryClient.getServices())
|
||||
.thenReturn(Arrays.asList("SERVICE1", "Service2"));
|
||||
.thenReturn(Flux.just("SERVICE1", "Service2"));
|
||||
whenInstance(discoveryClient, "SERVICE1",
|
||||
Collections.singletonMap("edge", "true"));
|
||||
whenInstance(discoveryClient, "Service2", Collections.emptyMap());
|
||||
return discoveryClient;
|
||||
}
|
||||
|
||||
private void whenInstance(DiscoveryClient discoveryClient, String serviceId,
|
||||
Map<String, String> metadata) {
|
||||
private void whenInstance(ReactiveDiscoveryClient discoveryClient,
|
||||
String serviceId, Map<String, String> metadata) {
|
||||
DefaultServiceInstance instance1 = new DefaultServiceInstance(serviceId,
|
||||
"localhost", 8001, false, metadata);
|
||||
when(discoveryClient.getInstances(serviceId))
|
||||
.thenReturn(Collections.singletonList(instance1));
|
||||
.thenReturn(Flux.just(instance1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,18 +19,20 @@ package org.springframework.cloud.gateway.discovery;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.runners.Enclosed;
|
||||
import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
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.ReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.gateway.config.LoadBalancerProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(Enclosed.class)
|
||||
public class GatewayDiscoveryClientAutoConfigurationTests {
|
||||
@@ -80,8 +82,10 @@ public class GatewayDiscoveryClientAutoConfigurationTests {
|
||||
protected static class Config {
|
||||
|
||||
@Bean
|
||||
DiscoveryClient discoveryClient() {
|
||||
return mock(DiscoveryClient.class);
|
||||
ReactiveDiscoveryClient discoveryClient() {
|
||||
ReactiveDiscoveryClient discoveryClient = mock(ReactiveDiscoveryClient.class);
|
||||
when(discoveryClient.getServices()).thenReturn(Flux.empty());
|
||||
return discoveryClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user