Gh 595 add serviceinstancelistsupplier (#607)
* Add ServiceInstanceListSupplier and its implementations. Deprecate ServiceInstanceSupplier and its implementations. Fixes gh-595. * Switch to non-parameterised type. * Switch autoConfiguration and tests to new implementation. * Update docs and javadocs. Remove deprecated TODOs. * Fix after code review.
This commit is contained in:
committed by
GitHub
parent
1f6a4b1b37
commit
da0ce3c4c8
@@ -418,7 +418,7 @@ will be handled by a non-reactive `LoadBalancerClient` under the hood. Additiona
|
||||
spring-cloud-starter-netflix-ribbon is already in maintenance mode, so we do not recommend
|
||||
adding it to new projects.
|
||||
|
||||
IMPORTANT: In order to make use of the more efficient cached version of `ServiceInstanceSupplier`,
|
||||
IMPORTANT: In order to make use of the more efficient cached version of `ServiceInstanceListSupplier`,
|
||||
`spring-cloud-starter-loadbalancer` will *enable caching* by default.
|
||||
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html[Spring Boot Caching]
|
||||
mechanism will be used under the hood. If you don't want caching to be used, you can set
|
||||
|
||||
@@ -24,10 +24,13 @@ import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
|
||||
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceSupplier;
|
||||
import org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier;
|
||||
import org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceSupplier;
|
||||
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
|
||||
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
|
||||
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
|
||||
import org.springframework.cloud.loadbalancer.core.ServiceInstanceSupplier;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -43,13 +46,27 @@ import org.springframework.core.env.Environment;
|
||||
@ConditionalOnDiscoveryEnabled
|
||||
public class LoadBalancerClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(DiscoveryClient.class)
|
||||
@ConditionalOnMissingBean
|
||||
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
|
||||
DiscoveryClient discoveryClient, Environment env,
|
||||
ObjectProvider<CacheManager> cacheManager) {
|
||||
DiscoveryClientServiceInstanceListSupplier delegate = new DiscoveryClientServiceInstanceListSupplier(
|
||||
discoveryClient, env);
|
||||
if (cacheManager.getIfAvailable() != null) {
|
||||
return new CachingServiceInstanceListSupplier(delegate,
|
||||
cacheManager.getIfAvailable());
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(DiscoveryClient.class)
|
||||
@ConditionalOnMissingBean
|
||||
public ServiceInstanceSupplier discoveryClientServiceInstanceSupplier(
|
||||
DiscoveryClient discoveryClient, Environment env,
|
||||
ObjectProvider<CacheManager> cacheManager) {
|
||||
// TODO: bean post processor to enable caching?
|
||||
DiscoveryClientServiceInstanceSupplier delegate = new DiscoveryClientServiceInstanceSupplier(
|
||||
discoveryClient, env);
|
||||
if (cacheManager.getIfAvailable() != null) {
|
||||
@@ -65,8 +82,8 @@ public class LoadBalancerClientConfiguration {
|
||||
Environment environment,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
|
||||
return new RoundRobinLoadBalancer(name, loadBalancerClientFactory
|
||||
.getLazyProvider(name, ServiceInstanceSupplier.class));
|
||||
return new RoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,
|
||||
ServiceInstanceListSupplier.class), name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.loadbalancer.core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import reactor.cache.CacheFlux;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* A {@link ServiceInstanceListSupplier} implementation that tries retrieving
|
||||
* {@link ServiceInstance} objects from cache; if none found, retrieves instances using
|
||||
* {@link DiscoveryClientServiceInstanceListSupplier}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class CachingServiceInstanceListSupplier implements ServiceInstanceListSupplier {
|
||||
|
||||
/**
|
||||
* Name of the service cache instance.
|
||||
*/
|
||||
public static final String SERVICE_INSTANCE_CACHE_NAME = CachingServiceInstanceListSupplier.class
|
||||
.getSimpleName() + "Cache";
|
||||
|
||||
private final ServiceInstanceListSupplier delegate;
|
||||
|
||||
private final Flux<List<ServiceInstance>> serviceInstances;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public CachingServiceInstanceListSupplier(ServiceInstanceListSupplier delegate,
|
||||
CacheManager cacheManager) {
|
||||
this.delegate = delegate;
|
||||
this.serviceInstances = CacheFlux.lookup(key -> {
|
||||
// TODO: configurable cache name
|
||||
Cache cache = cacheManager.getCache(SERVICE_INSTANCE_CACHE_NAME);
|
||||
List<ServiceInstance> list = Objects.requireNonNull(cache).get(key,
|
||||
List.class);
|
||||
if (list == null || list.isEmpty()) {
|
||||
return Mono.empty();
|
||||
}
|
||||
return Flux.just(list).materialize().collectList();
|
||||
}, delegate.getServiceId()).onCacheMissResume(this.delegate)
|
||||
.andWriteWith((key, signals) -> Flux.fromIterable(signals).dematerialize()
|
||||
.doOnNext(instances -> {
|
||||
Cache cache = cacheManager
|
||||
.getCache(SERVICE_INSTANCE_CACHE_NAME);
|
||||
Objects.requireNonNull(cache).put(key, instances);
|
||||
}).then());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceId() {
|
||||
return delegate.getServiceId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<List<ServiceInstance>> get() {
|
||||
return serviceInstances;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,8 +27,10 @@ import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link CachingServiceInstanceListSupplier} instead.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Deprecated
|
||||
public class CachingServiceInstanceSupplier implements ServiceInstanceSupplier {
|
||||
|
||||
/**
|
||||
@@ -46,10 +48,8 @@ public class CachingServiceInstanceSupplier implements ServiceInstanceSupplier {
|
||||
CacheManager cacheManager) {
|
||||
this.delegate = delegate;
|
||||
this.serviceInstances = CacheFlux.lookup(key -> {
|
||||
Cache cache = cacheManager.getCache(SERVICE_INSTANCE_CACHE_NAME); // TODO:
|
||||
// configurable
|
||||
// cache
|
||||
// name
|
||||
// TODO: configurable cache name
|
||||
Cache cache = cacheManager.getCache(SERVICE_INSTANCE_CACHE_NAME);
|
||||
List<ServiceInstance> list = cache.get(key, List.class);
|
||||
if (list == null || list.isEmpty()) {
|
||||
return Mono.empty();
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.loadbalancer.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import static org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory.PROPERTY_NAME;
|
||||
|
||||
/**
|
||||
* A discovery-client-based {@link ServiceInstanceListSupplier} implementation.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class DiscoveryClientServiceInstanceListSupplier
|
||||
implements ServiceInstanceListSupplier {
|
||||
|
||||
private final DiscoveryClient delegate;
|
||||
|
||||
private final String serviceId;
|
||||
|
||||
public DiscoveryClientServiceInstanceListSupplier(DiscoveryClient delegate,
|
||||
Environment environment) {
|
||||
this.delegate = delegate;
|
||||
this.serviceId = environment.getProperty(PROPERTY_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<List<ServiceInstance>> get() {
|
||||
return Flux.defer(() -> Flux.just(delegate.getInstances(serviceId)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,8 +27,10 @@ import org.springframework.core.env.Environment;
|
||||
import static org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory.PROPERTY_NAME;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link DiscoveryClientServiceInstanceListSupplier} instead.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Deprecated
|
||||
public class DiscoveryClientServiceInstanceSupplier implements ServiceInstanceSupplier {
|
||||
|
||||
private final DiscoveryClient delegate;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.loadbalancer.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* A no-op implementation of {@link ServiceInstanceListSupplier}.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class NoopServiceInstanceListSupplier implements ServiceInstanceListSupplier {
|
||||
|
||||
@Override
|
||||
public String getServiceId() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<List<ServiceInstance>> get() {
|
||||
return Flux.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.loadbalancer.core;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* A no-op implementation of {@link ServiceInstanceSupplier}.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @deprecated Use {@link NoopServiceInstanceListSupplier} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class NoopServiceInstanceSupplier implements ServiceInstanceSupplier {
|
||||
|
||||
@Override
|
||||
public String getServiceId() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<ServiceInstance> get() {
|
||||
return Flux.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.loadbalancer.core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -31,7 +32,10 @@ import org.springframework.cloud.client.loadbalancer.reactive.Request;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.Response;
|
||||
|
||||
/**
|
||||
* A Round-Robin-based implementation of {@link ReactorServiceInstanceLoadBalancer}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
|
||||
|
||||
@@ -39,15 +43,59 @@ public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalance
|
||||
|
||||
private final AtomicInteger position;
|
||||
|
||||
private final ObjectProvider<ServiceInstanceSupplier> serviceInstanceSupplier;
|
||||
@Deprecated
|
||||
private ObjectProvider<ServiceInstanceSupplier> serviceInstanceSupplier;
|
||||
|
||||
private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
|
||||
|
||||
private final String serviceId;
|
||||
|
||||
/**
|
||||
* @param serviceId id of the service for which to choose an instance
|
||||
* @param serviceInstanceSupplier a provider of {@link ServiceInstanceSupplier} that
|
||||
* will be used to get available instances
|
||||
* @deprecated Use {@link #RoundRobinLoadBalancer(ObjectProvider, String)}} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public RoundRobinLoadBalancer(String serviceId,
|
||||
ObjectProvider<ServiceInstanceSupplier> serviceInstanceSupplier) {
|
||||
this(serviceId, serviceInstanceSupplier, new Random().nextInt(1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceInstanceListSupplierProvider a provider of
|
||||
* {@link ServiceInstanceListSupplier} that will be used to get available instances
|
||||
* @param serviceId id of the service for which to choose an instance
|
||||
*/
|
||||
public RoundRobinLoadBalancer(
|
||||
ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
|
||||
String serviceId) {
|
||||
this(serviceInstanceListSupplierProvider, serviceId, new Random().nextInt(1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceInstanceListSupplierProvider a provider of
|
||||
* {@link ServiceInstanceListSupplier} that will be used to get available instances
|
||||
* @param serviceId id of the service for which to choose an instance
|
||||
* @param seedPosition Round Robin element position marker
|
||||
*/
|
||||
public RoundRobinLoadBalancer(
|
||||
ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
|
||||
String serviceId, int seedPosition) {
|
||||
this.serviceId = serviceId;
|
||||
this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
|
||||
this.position = new AtomicInteger(seedPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceId id of the service for which to choose an instance
|
||||
* @param serviceInstanceSupplier a provider of {@link ServiceInstanceSupplier} that
|
||||
* will be used to get available instances
|
||||
* @param seedPosition Round Robin element position marker
|
||||
* @deprecated Use {@link #RoundRobinLoadBalancer(ObjectProvider, String, int)}}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public RoundRobinLoadBalancer(String serviceId,
|
||||
ObjectProvider<ServiceInstanceSupplier> serviceInstanceSupplier,
|
||||
int seedPosition) {
|
||||
@@ -62,19 +110,29 @@ public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalance
|
||||
// src/main/java/netflix/ocelli/loadbalancer/RoundRobinLoadBalancer.java
|
||||
public Mono<Response<ServiceInstance>> choose(Request request) {
|
||||
// TODO: move supplier to Request?
|
||||
ServiceInstanceSupplier supplier = this.serviceInstanceSupplier.getIfAvailable();
|
||||
return supplier.get().collectList().map(instances -> {
|
||||
if (instances.isEmpty()) {
|
||||
log.warn("No servers available for service: " + this.serviceId);
|
||||
return new EmptyResponse();
|
||||
}
|
||||
// TODO: enforce order?
|
||||
int pos = Math.abs(this.position.incrementAndGet());
|
||||
// Temporary conditional logic till deprecated members are removed.
|
||||
if (serviceInstanceListSupplierProvider != null) {
|
||||
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
|
||||
.getIfAvailable(NoopServiceInstanceListSupplier::new);
|
||||
return supplier.get().next().map(this::getInstanceResponse);
|
||||
}
|
||||
ServiceInstanceSupplier supplier = this.serviceInstanceSupplier
|
||||
.getIfAvailable(NoopServiceInstanceSupplier::new);
|
||||
return supplier.get().collectList().map(this::getInstanceResponse);
|
||||
}
|
||||
|
||||
ServiceInstance instance = instances.get(pos % instances.size());
|
||||
private Response<ServiceInstance> getInstanceResponse(
|
||||
List<ServiceInstance> instances) {
|
||||
if (instances.isEmpty()) {
|
||||
log.warn("No servers available for service: " + this.serviceId);
|
||||
return new EmptyResponse();
|
||||
}
|
||||
// TODO: enforce order?
|
||||
int pos = Math.abs(this.position.incrementAndGet());
|
||||
|
||||
return new DefaultResponse(instance);
|
||||
});
|
||||
ServiceInstance instance = instances.get(pos % instances.size());
|
||||
|
||||
return new DefaultResponse(instance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.loadbalancer.core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* A {@link Supplier} of lists of {@link ServiceInstance} objects.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public interface ServiceInstanceListSupplier
|
||||
extends Supplier<Flux<List<ServiceInstance>>> {
|
||||
|
||||
String getServiceId();
|
||||
|
||||
}
|
||||
@@ -24,7 +24,9 @@ import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @deprecated Use {@link ServiceInstanceListSupplier} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ServiceInstanceSupplier extends Supplier<Flux<ServiceInstance>> {
|
||||
|
||||
String getServiceId();
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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
|
||||
*
|
||||
* https://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.loadbalancer.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
|
||||
|
||||
/**
|
||||
* Utility class for service instances.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public final class ServiceInstanceListSuppliers {
|
||||
|
||||
private ServiceInstanceListSuppliers() {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
}
|
||||
|
||||
public static ServiceInstanceListSupplier from(String serviceId,
|
||||
ServiceInstance... instances) {
|
||||
return new ServiceInstanceListSupplier() {
|
||||
@Override
|
||||
public Flux<List<ServiceInstance>> get() {
|
||||
return Flux.just(Arrays.asList(instances));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static ObjectProvider<ServiceInstanceListSupplier> toProvider(String serviceId,
|
||||
ServiceInstance... instances) {
|
||||
return new SimpleObjectProvider<>(from(serviceId, instances));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,7 +26,9 @@ import org.springframework.cloud.loadbalancer.core.ServiceInstanceSupplier;
|
||||
* Utility class for service instances.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @deprecated Use {@link ServiceInstanceListSuppliers} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ServiceInstanceSuppliers {
|
||||
|
||||
private ServiceInstanceSuppliers() {
|
||||
|
||||
@@ -96,7 +96,7 @@ class BlockingLoadBalancerClientTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void exceptionThrownIfInstanceNotAvailableForRequestExecution() throws IOException {
|
||||
void exceptionThrownIfInstanceNotAvailableForRequestExecution() {
|
||||
try {
|
||||
final String result = "result";
|
||||
Object actualResult = loadBalancerClient.execute("unknownservice",
|
||||
|
||||
@@ -34,7 +34,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class BlockingLoadBalancerClientAutoConfigurationTests {
|
||||
|
||||
ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
|
||||
private ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
|
||||
.withPropertyValues("spring.cloud.loadbalancer.ribbon.enabled=false",
|
||||
"debug=true")
|
||||
.withConfiguration(AutoConfigurations.of(LoadBalancerAutoConfiguration.class,
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.springframework.cloud.client.loadbalancer.reactive.Response;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.cloud.loadbalancer.support.ServiceInstanceListSuppliers;
|
||||
import org.springframework.cloud.loadbalancer.support.ServiceInstanceSuppliers;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -51,7 +52,7 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class LoadBalancerTest {
|
||||
public class LoadBalancerTests {
|
||||
|
||||
@Autowired
|
||||
private LoadBalancerClientFactory clientFactory;
|
||||
@@ -124,9 +125,20 @@ public class LoadBalancerTest {
|
||||
assertLoadBalancer(loadBalancer, Arrays.asList("1host", "2host-secure"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticConfigurationWorksWithServiceInstanceListSupplier() {
|
||||
String serviceId = "test1";
|
||||
RoundRobinLoadBalancer loadBalancer = new RoundRobinLoadBalancer(
|
||||
ServiceInstanceListSuppliers.toProvider(serviceId,
|
||||
instance(serviceId, "1host", false),
|
||||
instance(serviceId, "2host-secure", true)),
|
||||
serviceId, -1);
|
||||
assertLoadBalancer(loadBalancer, Arrays.asList("1host", "2host-secure"));
|
||||
}
|
||||
|
||||
private DefaultServiceInstance instance(String serviceId, String host,
|
||||
boolean secure) {
|
||||
return new DefaultServiceInstance(serviceId, host, 80, secure);
|
||||
return new DefaultServiceInstance(serviceId, serviceId, host, 80, secure);
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -147,8 +159,8 @@ public class LoadBalancerTest {
|
||||
public RoundRobinLoadBalancer roundRobinContextLoadBalancer(
|
||||
LoadBalancerClientFactory clientFactory, Environment env) {
|
||||
String serviceId = clientFactory.getName(env);
|
||||
return new RoundRobinLoadBalancer(serviceId, clientFactory
|
||||
.getLazyProvider(serviceId, ServiceInstanceSupplier.class), -1);
|
||||
return new RoundRobinLoadBalancer(clientFactory.getLazyProvider(serviceId,
|
||||
ServiceInstanceListSupplier.class), serviceId, -1);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user