Remove ribbon integration (#691)
* Remove Ribbon-specific configuration. * Remove Ribbon-specific docs. Refactor.
This commit is contained in:
committed by
GitHub
parent
8a899f0bb0
commit
2710c8251d
@@ -34,7 +34,6 @@
|
||||
|spring.cloud.loadbalancer.health-check.interval | 30s | Interval for rerunning the HealthCheck scheduler.
|
||||
|spring.cloud.loadbalancer.health-check.path | |
|
||||
|spring.cloud.loadbalancer.retry.enabled | true |
|
||||
|spring.cloud.loadbalancer.ribbon.enabled | true | Causes `RibbonLoadBalancerClient` to be used by default.
|
||||
|spring.cloud.refresh.enabled | true | Enables autoconfiguration for the refresh scope and associated features.
|
||||
|spring.cloud.refresh.extra-refreshable | true | Additional class names for beans to post process into refresh scope.
|
||||
|spring.cloud.service-registry.auto-registration.enabled | true | Whether service auto-registration is enabled. Defaults to true.
|
||||
|
||||
@@ -389,18 +389,10 @@ CAUTION: A `RestTemplate` bean is no longer created through auto-configuration.
|
||||
Individual applications must create it.
|
||||
|
||||
The URI needs to use a virtual host name (that is, a service name, not a host name).
|
||||
The Ribbon client is used to create a full physical address.
|
||||
See {githubroot}/spring-cloud-netflix/blob/master/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java[`RibbonAutoConfiguration`] for the details of how the `RestTemplate` is set up.
|
||||
The BlockingLoadBalancerClient is used to create a full physical address.
|
||||
|
||||
IMPORTANT: To use a load-balanced `RestTemplate`, you need to have a load-balancer implementation in your classpath.
|
||||
The recommended implementation is `BlockingLoadBalancerClient`.
|
||||
Add <<spring-cloud-loadbalancer-starter, Spring Cloud LoadBalancer starter>> to your project in order to use it.
|
||||
The
|
||||
`RibbonLoadBalancerClient` also can be used, but it's now under maintenance and we do not recommend adding it to new projects.
|
||||
|
||||
WARNING: By default, if you have both `RibbonLoadBalancerClient` and `BlockingLoadBalancerClient`, to
|
||||
preserve backward compatibility, `RibbonLoadBalancerClient` is used.
|
||||
To override it, you can set the `spring.cloud.loadbalancer.ribbon.enabled` property to `false`.
|
||||
|
||||
[[webclinet-loadbalancer-client]]
|
||||
=== Spring WebClient as a Load Balancer Client
|
||||
@@ -434,29 +426,19 @@ public class MyClass {
|
||||
====
|
||||
|
||||
The URI needs to use a virtual host name (that is, a service name, not a host name).
|
||||
The Ribbon client or Spring Cloud LoadBalancer is used to create a full physical address.
|
||||
The Spring Cloud LoadBalancer is used to create a full physical address.
|
||||
|
||||
IMPORTANT: If you want to use a `@LoadBalanced WebClient.Builder`, you need to have a load balancer
|
||||
implementation in the classpath. We recommend that you add the
|
||||
<<spring-cloud-loadbalancer-starter, Spring Cloud LoadBalancer starter>> to your project.
|
||||
Then, `ReactiveLoadBalancer` is used underneath.
|
||||
Alternatively, this functionality also works with `spring-cloud-starter-netflix-ribbon`, but the request
|
||||
is handled by a non-reactive `LoadBalancerClient` under the hood. Additionally,
|
||||
`spring-cloud-starter-netflix-ribbon` is already in maintenance mode, so we do not recommend
|
||||
adding it to new projects.
|
||||
If you have both `spring-cloud-starter-loadbalancer` and `spring-cloud-starter-netflix-ribbon`
|
||||
in your classpath, Ribbon is used by default. To switch to Spring Cloud LoadBalancer,
|
||||
set the `spring.cloud.loadbalancer.ribbon.enabled` property to `false`.
|
||||
|
||||
==== Retrying Failed Requests
|
||||
|
||||
A load-balanced `RestTemplate` can be configured to retry failed requests.
|
||||
By default, this logic is disabled.
|
||||
You can enable it by adding link:https://github.com/spring-projects/spring-retry[Spring Retry] to your application's classpath.
|
||||
The load-balanced `RestTemplate` honors some of the Ribbon configuration values related to retrying failed requests.
|
||||
You can use `client.ribbon.MaxAutoRetries`, `client.ribbon.MaxAutoRetriesNextServer`, and `client.ribbon.OkToRetryOnAllOperations` properties.
|
||||
If you would like to disable the retry logic with Spring Retry on the classpath, you can set `spring.cloud.loadbalancer.retry.enabled=false`.
|
||||
See the https://github.com/Netflix/ribbon/wiki/Getting-Started#the-properties-file-sample-clientproperties[Ribbon documentation] for a description of what these properties do.
|
||||
|
||||
If you would like to implement a `BackOffPolicy` in your retries, you need to create a bean of type `LoadBalancedRetryFactory` and override the `createBackOffPolicy` method:
|
||||
|
||||
@@ -478,8 +460,6 @@ public class MyConfiguration {
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: `client` in the preceding examples should be replaced with your Ribbon client's name.
|
||||
|
||||
If you want to add one or more `RetryListener` implementations to your retry functionality, you need to
|
||||
create a bean of type `LoadBalancedRetryListenerFactory` and return the `RetryListener` array
|
||||
you would like to use for a given service, as the following example shows:
|
||||
@@ -649,16 +629,9 @@ public class MyClass {
|
||||
The URI needs to use a virtual host name (that is, a service name, not a host name).
|
||||
The `ReactorLoadBalancer` is used to create a full physical address.
|
||||
|
||||
NOTE: By default, if you have `spring-cloud-netflix-ribbon` in your classpath, <<load-balancer-exchange-filter-function,`LoadBalancerExchangeFilterFunction`>>
|
||||
is used to maintain backward compatibility. To use
|
||||
`ReactorLoadBalancerExchangeFilterFunction`, set the `spring.cloud.loadbalancer.ribbon.enabled` property
|
||||
to `false`.
|
||||
|
||||
[[load-balancer-exchange-filter-function]]
|
||||
==== Spring WebFlux `WebClient` with a Non-reactive Load Balancer Client
|
||||
|
||||
If you you do not have <<spring-cloud-loadbalancer-starter, Spring Cloud LoadBalancer starter>> in your project
|
||||
but you do have spring-cloud-starter-netflix-ribbon, you can still use `WebClient` with `LoadBalancerClient`.
|
||||
If `spring-webflux` is on the classpath, `LoadBalancerExchangeFilterFunction`
|
||||
is auto-configured. Note, however, that this
|
||||
uses a non-reactive client under the hood.
|
||||
@@ -1004,9 +977,6 @@ NOTE: Spring Cloud LoadBalancer starter includes
|
||||
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html[Spring Boot Caching]
|
||||
and https://github.com/stoyanr[Evictor].
|
||||
|
||||
WARNING: If you have both Ribbon and Spring Cloud LoadBalancer int the classpath, in order to maintain backward compatibility, Ribbon-based implementations will be used by default.
|
||||
In order to switch to using Spring Cloud LoadBalancer under the hood, make sure you set the property `spring.cloud.loadbalancer.ribbon.enabled` to `false`.
|
||||
|
||||
[[custom-loadbalancer-configuration]]
|
||||
=== Passing Your Own Spring Cloud LoadBalancer Configuration
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.http.client.AsyncClientHttpRequestInterceptor;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
|
||||
/**
|
||||
* Auto-configuration for Ribbon (client-side load balancing).
|
||||
* Auto-configuration for blocking client-side load balancing.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
@@ -49,13 +49,10 @@ public class AsyncLoadBalancerAutoConfiguration {
|
||||
@Bean
|
||||
public SmartInitializingSingleton loadBalancedAsyncRestTemplateInitializer(
|
||||
final List<AsyncRestTemplateCustomizer> customizers) {
|
||||
return new SmartInitializingSingleton() {
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
for (AsyncRestTemplate restTemplate : AsyncRestTemplateCustomizerConfig.this.restTemplates) {
|
||||
for (AsyncRestTemplateCustomizer customizer : customizers) {
|
||||
customizer.customize(restTemplate);
|
||||
}
|
||||
return () -> {
|
||||
for (AsyncRestTemplate restTemplate : AsyncRestTemplateCustomizerConfig.this.restTemplates) {
|
||||
for (AsyncRestTemplateCustomizer customizer : customizers) {
|
||||
customizer.customize(restTemplate);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -75,14 +72,11 @@ public class AsyncLoadBalancerAutoConfiguration {
|
||||
@Bean
|
||||
public AsyncRestTemplateCustomizer asyncRestTemplateCustomizer(
|
||||
final AsyncLoadBalancerInterceptor loadBalancerInterceptor) {
|
||||
return new AsyncRestTemplateCustomizer() {
|
||||
@Override
|
||||
public void customize(AsyncRestTemplate restTemplate) {
|
||||
List<AsyncClientHttpRequestInterceptor> list = new ArrayList<>(
|
||||
restTemplate.getInterceptors());
|
||||
list.add(loadBalancerInterceptor);
|
||||
restTemplate.setInterceptors(list);
|
||||
}
|
||||
return restTemplate -> {
|
||||
List<AsyncClientHttpRequestInterceptor> list = new ArrayList<>(
|
||||
restTemplate.getInterceptors());
|
||||
list.add(loadBalancerInterceptor);
|
||||
restTemplate.setInterceptors(list);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.retry.support.RetryTemplate;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Auto-configuration for Ribbon (client-side load balancing).
|
||||
* Auto-configuration for blocking (client-side load balancing).
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
@@ -79,7 +79,7 @@ public class LoadBalancerAutoConfiguration {
|
||||
static class LoadBalancerInterceptorConfig {
|
||||
|
||||
@Bean
|
||||
public LoadBalancerInterceptor ribbonInterceptor(
|
||||
public LoadBalancerInterceptor loadBalancerInterceptor(
|
||||
LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancerRequestFactory requestFactory) {
|
||||
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
|
||||
@@ -124,7 +124,7 @@ public class LoadBalancerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public RetryLoadBalancerInterceptor ribbonInterceptor(
|
||||
public RetryLoadBalancerInterceptor loadBalancerInterceptor(
|
||||
LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancerRetryProperties properties,
|
||||
LoadBalancerRequestFactory requestFactory,
|
||||
|
||||
@@ -18,11 +18,9 @@ package org.springframework.cloud.client.loadbalancer.reactive;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -57,7 +55,6 @@ public class LoadBalancerBeanPostProcessorAutoConfiguration {
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Conditional(OnNoRibbonDefaultCondition.class)
|
||||
@ConditionalOnBean(ReactiveLoadBalancer.Factory.class)
|
||||
protected static class ReactorDeferringLoadBalancerFilterConfig {
|
||||
|
||||
@@ -71,22 +68,6 @@ public class LoadBalancerBeanPostProcessorAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean(LoadBalancerClient.class)
|
||||
@AutoConfigureAfter(ReactorDeferringLoadBalancerFilterConfig.class)
|
||||
@Deprecated
|
||||
protected static class ReactiveLoadBalancerConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
DeferringLoadBalancerExchangeFilterFunction<LoadBalancerExchangeFilterFunction> deferringLoadBalancerExchangeFilterFunction(
|
||||
ObjectProvider<LoadBalancerExchangeFilterFunction> exchangeFilterFunctionProvider) {
|
||||
return new DeferringLoadBalancerExchangeFilterFunction<>(
|
||||
exchangeFilterFunctionProvider);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class OnAnyLoadBalancerImplementationPresentCondition
|
||||
extends AnyNestedCondition {
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFunction;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Ryan Baxter
|
||||
* @deprecated Use {@link ReactorLoadBalancerExchangeFilterFunction} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class LoadBalancerExchangeFilterFunction implements ExchangeFilterFunction {
|
||||
|
||||
private static Log logger = LogFactory
|
||||
.getLog(LoadBalancerExchangeFilterFunction.class);
|
||||
|
||||
private final LoadBalancerClient loadBalancerClient;
|
||||
|
||||
public LoadBalancerExchangeFilterFunction(LoadBalancerClient loadBalancerClient) {
|
||||
this.loadBalancerClient = loadBalancerClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
|
||||
URI originalUrl = request.url();
|
||||
String serviceId = originalUrl.getHost();
|
||||
if (serviceId == null) {
|
||||
String msg = String.format(
|
||||
"Request URI does not contain a valid hostname: %s",
|
||||
originalUrl.toString());
|
||||
logger.warn(msg);
|
||||
return Mono.just(
|
||||
ClientResponse.create(HttpStatus.BAD_REQUEST).body(msg).build());
|
||||
}
|
||||
// TODO: reactive lb client
|
||||
ServiceInstance instance = this.loadBalancerClient.choose(serviceId);
|
||||
if (instance == null) {
|
||||
String msg = String.format(
|
||||
"Load balancer does not contain an instance for the service %s",
|
||||
serviceId);
|
||||
logger.warn(msg);
|
||||
return Mono.just(ClientResponse.create(HttpStatus.SERVICE_UNAVAILABLE)
|
||||
.body(msg).build());
|
||||
}
|
||||
URI uri = this.loadBalancerClient.reconstructURI(instance, originalUrl);
|
||||
ClientRequest newRequest = ClientRequest.method(request.method(), uri)
|
||||
.headers(headers -> headers.addAll(request.headers()))
|
||||
.cookies(cookies -> cookies.addAll(request.cookies()))
|
||||
.attributes(attributes -> attributes.putAll(request.attributes()))
|
||||
.body(request.body()).build();
|
||||
return next.exchange(newRequest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
import java.util.concurrent.locks.Condition;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
|
||||
/**
|
||||
* A {@link Condition} that verifies that Ribbon is either not present or disabled.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.2.1
|
||||
*/
|
||||
public class OnNoRibbonDefaultCondition extends AnyNestedCondition {
|
||||
|
||||
public OnNoRibbonDefaultCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.ribbon.enabled",
|
||||
havingValue = "false")
|
||||
static class RibbonNotEnabled {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass("org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient")
|
||||
static class RibbonLoadBalancerNotPresent {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @deprecated in favour of {@link ReactorLoadBalancerClientAutoConfiguration}
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(WebClient.class)
|
||||
@ConditionalOnBean(LoadBalancerClient.class)
|
||||
@AutoConfigureAfter(ReactorLoadBalancerClientAutoConfiguration.class)
|
||||
@ConditionalOnMissingBean(ReactorLoadBalancerExchangeFilterFunction.class)
|
||||
@Deprecated
|
||||
public class ReactiveLoadBalancerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public LoadBalancerExchangeFilterFunction loadBalancerExchangeFilterFunction(
|
||||
LoadBalancerClient client) {
|
||||
return new LoadBalancerExchangeFilterFunction(client);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,18 +16,11 @@
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer.reactive;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
@@ -44,46 +37,11 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
@ConditionalOnBean(ReactiveLoadBalancer.Factory.class)
|
||||
public class ReactorLoadBalancerClientAutoConfiguration {
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@Bean
|
||||
@ConditionalOnClass(
|
||||
name = "org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient")
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.ribbon.enabled",
|
||||
matchIfMissing = true)
|
||||
public ReactorLoadBalancerClientRibbonWarnLogger reactorLoadBalancerClientRibbonWarnLogger() {
|
||||
return new ReactorLoadBalancerClientRibbonWarnLogger();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Conditional(OnNoRibbonDefaultCondition.class)
|
||||
protected static class ReactorLoadBalancerExchangeFilterFunctionConfig {
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@Bean
|
||||
public ReactorLoadBalancerExchangeFilterFunction loadBalancerExchangeFilterFunction(
|
||||
ReactiveLoadBalancer.Factory loadBalancerFactory) {
|
||||
return new ReactorLoadBalancerExchangeFilterFunction(loadBalancerFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ReactorLoadBalancerClientRibbonWarnLogger {
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(ReactorLoadBalancerClientRibbonWarnLogger.class);
|
||||
|
||||
@PostConstruct
|
||||
void logWarning() {
|
||||
if (LOG.isWarnEnabled()) {
|
||||
LOG.warn("You have RibbonLoadBalancerClient on your classpath. "
|
||||
+ "LoadBalancerExchangeFilterFunction that uses it under the "
|
||||
+ "hood will be used by default. Spring Cloud Ribbon is now in maintenance mode, "
|
||||
+ "so we suggest switching to "
|
||||
+ ReactorLoadBalancerExchangeFilterFunction.class.getSimpleName()
|
||||
+ " instead. In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false` or "
|
||||
+ "remove spring-cloud-starter-netflix-ribbon from your project.");
|
||||
}
|
||||
}
|
||||
|
||||
public ReactorLoadBalancerExchangeFilterFunction loadBalancerExchangeFilterFunction(
|
||||
ReactiveLoadBalancer.Factory loadBalancerFactory) {
|
||||
return new ReactorLoadBalancerExchangeFilterFunction(loadBalancerFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration
|
||||
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
|
||||
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
|
||||
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\
|
||||
org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancerAutoConfiguration,\
|
||||
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
|
||||
org.springframework.cloud.commons.httpclient.HttpClientConfiguration,\
|
||||
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
|
||||
|
||||
@@ -70,7 +70,7 @@ public class RetryLoadBalancerInterceptorTest {
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
public void setUp() {
|
||||
this.client = mock(LoadBalancerClient.class);
|
||||
this.lbProperties = new LoadBalancerRetryProperties();
|
||||
this.lbRequestFactory = mock(LoadBalancerRequestFactory.class);
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
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.boot.web.server.LocalServerPort;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties;
|
||||
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties.SimpleServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||
public class LoadBalancerExchangeFilterFunctionTests {
|
||||
|
||||
@Autowired
|
||||
private LoadBalancerExchangeFilterFunction lbFunction;
|
||||
|
||||
@Autowired
|
||||
private SimpleDiscoveryProperties properties;
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
SimpleServiceInstance instance = new SimpleServiceInstance();
|
||||
instance.setServiceId("testservice");
|
||||
instance.setUri(URI.create("http://localhost:" + this.port));
|
||||
this.properties.getInstances().put("testservice", Arrays.asList(instance));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterFunctionWorks() {
|
||||
String value = WebClient.builder().baseUrl("http://testservice")
|
||||
.filter(this.lbFunction).build().get().uri("/hello").retrieve()
|
||||
.bodyToMono(String.class).block();
|
||||
then(value).isEqualTo("Hello World");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoInstance() {
|
||||
ClientResponse clientResponse = WebClient.builder().baseUrl("http://foobar")
|
||||
.filter(this.lbFunction).build().get().exchange().block();
|
||||
then(clientResponse.statusCode()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoHostName() {
|
||||
ClientResponse clientResponse = WebClient.builder().baseUrl("http:///foobar")
|
||||
.filter(this.lbFunction).build().get().exchange().block();
|
||||
then(clientResponse.statusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@EnableDiscoveryClient
|
||||
@EnableAutoConfiguration
|
||||
@SpringBootConfiguration
|
||||
@RestController
|
||||
static class Config {
|
||||
|
||||
@RequestMapping("/hello")
|
||||
public String hello() {
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
@Bean
|
||||
LoadBalancerClient loadBalancerClient(DiscoveryClient discoveryClient) {
|
||||
return new LoadBalancerClient() {
|
||||
Random random = new Random();
|
||||
|
||||
@Override
|
||||
public <T> T execute(String serviceId, LoadBalancerRequest<T> request)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(String serviceId, ServiceInstance serviceInstance,
|
||||
LoadBalancerRequest<T> request) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI reconstructURI(ServiceInstance instance, URI original) {
|
||||
return UriComponentsBuilder.fromUri(original).host(instance.getHost())
|
||||
.port(instance.getPort()).build().toUri();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstance choose(String serviceId) {
|
||||
List<ServiceInstance> instances = discoveryClient
|
||||
.getInstances(serviceId);
|
||||
if (instances.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
int instanceIdx = this.random.nextInt(instances.size());
|
||||
return instances.get(instanceIdx);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
/*
|
||||
* 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.client.loadbalancer.reactive;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
import static org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerTestUtils.assertLoadBalanced;
|
||||
import static org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerTestUtils.getFilters;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Tim Ysewyn
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class ReactiveLoadBalancerAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void webClientBuilderGetsLoadBalancerInterceptor() {
|
||||
ConfigurableApplicationContext context = init(OneWebClientBuilder.class);
|
||||
final Map<String, WebClient.Builder> webClientBuilders = context
|
||||
.getBeansOfType(WebClient.Builder.class);
|
||||
|
||||
then(webClientBuilders).isNotNull().hasSize(1);
|
||||
WebClient.Builder webClientBuilder = webClientBuilders.values().iterator().next();
|
||||
then(webClientBuilder).isNotNull();
|
||||
|
||||
assertLoadBalanced(webClientBuilder, LoadBalancerExchangeFilterFunction.class);
|
||||
|
||||
final Map<String, OneWebClientBuilder.TestService> testServiceMap = context
|
||||
.getBeansOfType(OneWebClientBuilder.TestService.class);
|
||||
then(testServiceMap).isNotNull().hasSize(1);
|
||||
OneWebClientBuilder.TestService testService = testServiceMap.values().stream()
|
||||
.findFirst().get();
|
||||
assertLoadBalanced(testService.webClient,
|
||||
LoadBalancerExchangeFilterFunction.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleWebClientBuilders() {
|
||||
ConfigurableApplicationContext context = init(TwoWebClientBuilders.class);
|
||||
final Map<String, WebClient.Builder> webClientBuilders = context
|
||||
.getBeansOfType(WebClient.Builder.class);
|
||||
|
||||
then(webClientBuilders).hasSize(2);
|
||||
|
||||
TwoWebClientBuilders.Two two = context.getBean(TwoWebClientBuilders.Two.class);
|
||||
|
||||
then(two.loadBalanced).isNotNull();
|
||||
assertLoadBalanced(two.loadBalanced, LoadBalancerExchangeFilterFunction.class);
|
||||
|
||||
then(two.nonLoadBalanced).isNotNull();
|
||||
then(getFilters(two.nonLoadBalanced)).isNullOrEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noCustomWebClientBuilders() {
|
||||
ConfigurableApplicationContext context = init(NoWebClientBuilder.class);
|
||||
final Map<String, WebClient.Builder> webClientBuilders = context
|
||||
.getBeansOfType(WebClient.Builder.class);
|
||||
|
||||
then(webClientBuilders).hasSize(1);
|
||||
|
||||
WebClient.Builder builder = context.getBean(WebClient.Builder.class);
|
||||
|
||||
then(builder).isNotNull();
|
||||
then(getFilters(builder)).isNullOrEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationNotLoadedWhenReactorLoadBalancerExchangeFilterFunctionPresent() {
|
||||
ConfigurableApplicationContext context = init(
|
||||
ReactorLoadBalancerClientPresent.class);
|
||||
final Map<String, WebClient.Builder> webClientBuilders = context
|
||||
.getBeansOfType(WebClient.Builder.class);
|
||||
|
||||
then(webClientBuilders).hasSize(1);
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> context.getBean(LoadBalancerExchangeFilterFunction.class))
|
||||
.isInstanceOf(NoSuchBeanDefinitionException.class);
|
||||
|
||||
WebClient.Builder builder = context.getBean(WebClient.Builder.class);
|
||||
|
||||
then(builder).isNotNull();
|
||||
assertLoadBalanced(builder, ReactorLoadBalancerExchangeFilterFunction.class);
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext init(Class<?> config) {
|
||||
return LoadBalancerTestUtils.init(config,
|
||||
ReactiveLoadBalancerAutoConfiguration.class,
|
||||
LoadBalancerBeanPostProcessorAutoConfiguration.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class NoWebClientBuilder {
|
||||
|
||||
@Bean
|
||||
LoadBalancerClient loadBalancerClient() {
|
||||
return new NoopLoadBalancerClient();
|
||||
}
|
||||
|
||||
@Bean
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory() {
|
||||
return new LoadBalancedRetryFactory() {
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class ReactorLoadBalancerClientPresent extends OneWebClientBuilder {
|
||||
|
||||
@Bean
|
||||
ReactiveLoadBalancer.Factory<ServiceInstance> reactiveLoadBalancerFactory() {
|
||||
return serviceId -> new TestReactiveLoadBalancer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
ReactorLoadBalancerExchangeFilterFunction reactorLoadBalancerExchangeFilterFunction() {
|
||||
return new ReactorLoadBalancerExchangeFilterFunction(
|
||||
reactiveLoadBalancerFactory());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class OneWebClientBuilder extends NoWebClientBuilder {
|
||||
|
||||
@Bean
|
||||
@LoadBalanced
|
||||
WebClient.Builder loadBalancedWebClientBuilder() {
|
||||
return WebClient.builder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestService testService() {
|
||||
return new TestService(loadBalancedWebClientBuilder());
|
||||
}
|
||||
|
||||
private final class TestService {
|
||||
|
||||
public final WebClient webClient;
|
||||
|
||||
private TestService(WebClient.Builder builder) {
|
||||
this.webClient = builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class TwoWebClientBuilders extends OneWebClientBuilder {
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
WebClient.Builder webClientBuilder() {
|
||||
return WebClient.builder();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class Two {
|
||||
|
||||
@Autowired
|
||||
WebClient.Builder nonLoadBalanced;
|
||||
|
||||
@Autowired
|
||||
@LoadBalanced
|
||||
WebClient.Builder loadBalanced;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class NoopLoadBalancerClient implements LoadBalancerClient {
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
@Override
|
||||
public ServiceInstance choose(String serviceId) {
|
||||
return new DefaultServiceInstance(serviceId, serviceId, serviceId,
|
||||
this.random.nextInt(40000), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
|
||||
try {
|
||||
return request.apply(choose(serviceId));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(String serviceId, ServiceInstance serviceInstance,
|
||||
LoadBalancerRequest<T> request) throws IOException {
|
||||
try {
|
||||
return request.apply(choose(serviceId));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI reconstructURI(ServiceInstance instance, URI original) {
|
||||
return DefaultServiceInstance.getUri(instance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,25 +16,18 @@
|
||||
|
||||
package org.springframework.cloud.loadbalancer.config;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
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.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.OnNoRibbonDefaultCondition;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
@@ -49,49 +42,15 @@ import org.springframework.web.client.RestTemplate;
|
||||
@AutoConfigureBefore({
|
||||
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.class,
|
||||
AsyncLoadBalancerAutoConfiguration.class })
|
||||
@ConditionalOnClass(RestTemplate.class)
|
||||
public class BlockingLoadBalancerClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(
|
||||
name = "org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient")
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.ribbon.enabled",
|
||||
matchIfMissing = true)
|
||||
public BlockingLoadBalancerClientRibbonWarnLogger blockingLoadBalancerClientRibbonWarnLogger() {
|
||||
return new BlockingLoadBalancerClientRibbonWarnLogger();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(RestTemplate.class)
|
||||
@Conditional(OnNoRibbonDefaultCondition.class)
|
||||
protected static class BlockingLoadbalancerClientConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(LoadBalancerClientFactory.class)
|
||||
@Primary
|
||||
public BlockingLoadBalancerClient blockingLoadBalancerClient(
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
return new BlockingLoadBalancerClient(loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class BlockingLoadBalancerClientRibbonWarnLogger {
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(BlockingLoadBalancerClientRibbonWarnLogger.class);
|
||||
|
||||
@PostConstruct
|
||||
void logWarning() {
|
||||
if (LOG.isWarnEnabled()) {
|
||||
LOG.warn(
|
||||
"You already have RibbonLoadBalancerClient on your classpath. It will be used by default. "
|
||||
+ "As Spring Cloud Ribbon is in maintenance mode. We recommend switching to "
|
||||
+ BlockingLoadBalancerClient.class.getSimpleName()
|
||||
+ " instead. In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false` or "
|
||||
+ "remove spring-cloud-starter-netflix-ribbon from your project.");
|
||||
}
|
||||
}
|
||||
|
||||
@ConditionalOnBean(LoadBalancerClientFactory.class)
|
||||
@ConditionalOnMissingBean
|
||||
public LoadBalancerClient blockingLoadBalancerClient(
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
return new BlockingLoadBalancerClient(loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancerAutoConfiguration;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||
@@ -42,8 +41,7 @@ import org.springframework.core.env.Environment;
|
||||
@LoadBalancerClients
|
||||
@EnableConfigurationProperties(LoadBalancerProperties.class)
|
||||
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,
|
||||
LoadBalancerBeanPostProcessorAutoConfiguration.class,
|
||||
ReactiveLoadBalancerAutoConfiguration.class })
|
||||
LoadBalancerBeanPostProcessorAutoConfiguration.class })
|
||||
public class LoadBalancerAutoConfiguration {
|
||||
|
||||
private final ObjectProvider<List<LoadBalancerClientSpecification>> configurations;
|
||||
|
||||
@@ -32,13 +32,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.interceptor.CacheAspectSupport;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.OnNoRibbonDefaultCondition;
|
||||
import org.springframework.cloud.loadbalancer.cache.CaffeineBasedLoadBalancerCacheManager;
|
||||
import org.springframework.cloud.loadbalancer.cache.DefaultLoadBalancerCacheManager;
|
||||
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
|
||||
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
@@ -59,7 +57,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.cache.enabled",
|
||||
matchIfMissing = true)
|
||||
@EnableConfigurationProperties(LoadBalancerCacheProperties.class)
|
||||
@Conditional(OnNoRibbonDefaultCondition.class)
|
||||
public class LoadBalancerCacheAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"defaultValue": true,
|
||||
"name": "spring.cloud.loadbalancer.ribbon.enabled",
|
||||
"description": "Causes `RibbonLoadBalancerClient` to be used by default.",
|
||||
"type": "java.lang.Boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
|
||||
import org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration.BlockingLoadBalancerClientRibbonWarnLogger;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -35,17 +34,13 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class BlockingLoadBalancerClientAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
|
||||
.withPropertyValues("spring.cloud.loadbalancer.ribbon.enabled=false")
|
||||
.withConfiguration(AutoConfigurations.of(LoadBalancerAutoConfiguration.class,
|
||||
BlockingLoadBalancerClientAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void beansCreatedNormally() {
|
||||
applicationContextRunner.run(ctxt -> {
|
||||
assertThat(ctxt).hasSingleBean(BlockingLoadBalancerClient.class);
|
||||
assertThat(ctxt)
|
||||
.doesNotHaveBean(BlockingLoadBalancerClientRibbonWarnLogger.class);
|
||||
});
|
||||
applicationContextRunner.run(
|
||||
ctxt -> assertThat(ctxt).hasSingleBean(BlockingLoadBalancerClient.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -54,8 +49,6 @@ public class BlockingLoadBalancerClientAutoConfigurationTests {
|
||||
.withClassLoader(new FilteredClassLoader(RestTemplate.class))
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(BlockingLoadBalancerClient.class);
|
||||
assertThat(context).doesNotHaveBean(
|
||||
BlockingLoadBalancerClientRibbonWarnLogger.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user