Skip to content

Commit 84358e1

Browse files
committed
Merge remote-tracking branch 'origin/2.2.x'
2 parents b49f107 + c998d69 commit 84358e1

File tree

3 files changed

+227
-0
lines changed

3 files changed

+227
-0
lines changed

docs/src/main/asciidoc/spring-cloud-commons.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,8 @@ public class CustomLoadBalancerConfiguration {
943943

944944
TIP:: In order to make working on your own LoadBalancer configuration easier, we have added some utility methods in `ServiceInstanceListSuppliers` class.
945945

946+
TIP:: You can also use our alternative predefined configurations in place of the default ones by setting the value of `spring.cloud.loadbalancer.configurations` property to `zone-preference` to use `ZonePreferenceServiceInstanceListSupplier` with caching or to `health-check` to use `HealthCheckServiceInstanceListSupplier` with caching.
947+
946948
[[spring-cloud-loadbalancer-starter]]
947949
=== Spring Cloud LoadBalancer Starter
948950

spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.springframework.beans.factory.ObjectProvider;
2020
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2121
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
22+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2223
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
2324
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
2425
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
@@ -70,12 +71,36 @@ public static class ReactiveSupportConfiguration {
7071
@Bean
7172
@ConditionalOnBean(ReactiveDiscoveryClient.class)
7273
@ConditionalOnMissingBean
74+
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations",
75+
havingValue = "default", matchIfMissing = true)
7376
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
7477
ConfigurableApplicationContext context) {
7578
return ServiceInstanceListSuppliers.builder().withDiscoveryClient()
7679
.withCaching().build(context);
7780
}
7881

82+
@Bean
83+
@ConditionalOnBean(ReactiveDiscoveryClient.class)
84+
@ConditionalOnMissingBean
85+
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations",
86+
havingValue = "zone-preference")
87+
public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier(
88+
ConfigurableApplicationContext context) {
89+
return ServiceInstanceListSuppliers.builder().withDiscoveryClient()
90+
.withZonePreference().withCaching().build(context);
91+
}
92+
93+
@Bean
94+
@ConditionalOnBean(ReactiveDiscoveryClient.class)
95+
@ConditionalOnMissingBean
96+
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations",
97+
havingValue = "health-check")
98+
public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceListSupplier(
99+
ConfigurableApplicationContext context) {
100+
return ServiceInstanceListSuppliers.builder().withDiscoveryClient()
101+
.withHealthChecks().withCaching().build(context);
102+
}
103+
79104
@Bean
80105
@ConditionalOnBean(ReactiveDiscoveryClient.class)
81106
@ConditionalOnMissingBean
@@ -103,12 +128,36 @@ public static class BlockingSupportConfiguration {
103128
@Bean
104129
@ConditionalOnBean(DiscoveryClient.class)
105130
@ConditionalOnMissingBean
131+
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations",
132+
havingValue = "default", matchIfMissing = true)
106133
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
107134
ConfigurableApplicationContext context) {
108135
return ServiceInstanceListSuppliers.builder().withBlockingDiscoveryClient()
109136
.withCaching().build(context);
110137
}
111138

139+
@Bean
140+
@ConditionalOnBean(DiscoveryClient.class)
141+
@ConditionalOnMissingBean
142+
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations",
143+
havingValue = "zone-preference")
144+
public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier(
145+
ConfigurableApplicationContext context) {
146+
return ServiceInstanceListSuppliers.builder().withBlockingDiscoveryClient()
147+
.withZonePreference().withCaching().build(context);
148+
}
149+
150+
@Bean
151+
@ConditionalOnBean(DiscoveryClient.class)
152+
@ConditionalOnMissingBean
153+
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations",
154+
havingValue = "health-check")
155+
public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceListSupplier(
156+
ConfigurableApplicationContext context) {
157+
return ServiceInstanceListSuppliers.builder().withBlockingDiscoveryClient()
158+
.withHealthChecks().withCaching().build(context);
159+
}
160+
112161
@Bean
113162
@ConditionalOnBean(DiscoveryClient.class)
114163
@ConditionalOnMissingBean
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.loadbalancer.annotation;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.springframework.boot.autoconfigure.AutoConfigurations;
22+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
23+
import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration;
24+
import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration;
25+
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
26+
import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;
27+
import org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration;
28+
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
29+
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceSupplier;
30+
import org.springframework.cloud.loadbalancer.core.DelegatingServiceInstanceListSupplier;
31+
import org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier;
32+
import org.springframework.cloud.loadbalancer.core.HealthCheckServiceInstanceListSupplier;
33+
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
34+
import org.springframework.cloud.loadbalancer.core.ServiceInstanceSupplier;
35+
import org.springframework.cloud.loadbalancer.core.ZonePreferenceServiceInstanceListSupplier;
36+
import org.springframework.context.annotation.Bean;
37+
import org.springframework.context.annotation.Configuration;
38+
import org.springframework.web.reactive.function.client.WebClient;
39+
40+
import static org.assertj.core.api.BDDAssertions.then;
41+
42+
/**
43+
* Tests for {@link LoadBalancerClientConfiguration}.
44+
*
45+
* @author Olga Maciaszek-Sharma
46+
*/
47+
class LoadBalancerClientConfigurationTests {
48+
49+
ApplicationContextRunner reactiveDiscoveryClientRunner = new ApplicationContextRunner()
50+
.withConfiguration(AutoConfigurations.of(
51+
ReactiveCompositeDiscoveryClientAutoConfiguration.class,
52+
LoadBalancerCacheAutoConfiguration.class,
53+
LoadBalancerAutoConfiguration.class,
54+
LoadBalancerClientConfiguration.class));
55+
56+
ApplicationContextRunner blockingDiscoveryClientRunner = new ApplicationContextRunner()
57+
.withConfiguration(
58+
AutoConfigurations.of(CompositeDiscoveryClientAutoConfiguration.class,
59+
LoadBalancerCacheAutoConfiguration.class,
60+
LoadBalancerAutoConfiguration.class,
61+
LoadBalancerClientConfiguration.class));
62+
63+
@Test
64+
void shouldInstantiateDefaultServiceInstanceListSupplierWhenConfigurationsPropertyNotSet() {
65+
reactiveDiscoveryClientRunner.run(context -> {
66+
ServiceInstanceListSupplier supplier = context
67+
.getBean(ServiceInstanceListSupplier.class);
68+
then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class);
69+
then(((DelegatingServiceInstanceListSupplier) supplier).getDelegate())
70+
.isInstanceOf(DiscoveryClientServiceInstanceListSupplier.class);
71+
});
72+
}
73+
74+
@Test
75+
void shouldInstantiateDefaultServiceInstanceListSupplier() {
76+
reactiveDiscoveryClientRunner
77+
.withPropertyValues("spring.cloud.loadbalancer.configurations=default")
78+
.run(context -> {
79+
ServiceInstanceListSupplier supplier = context
80+
.getBean(ServiceInstanceListSupplier.class);
81+
then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class);
82+
then(((DelegatingServiceInstanceListSupplier) supplier).getDelegate())
83+
.isInstanceOf(
84+
DiscoveryClientServiceInstanceListSupplier.class);
85+
});
86+
}
87+
88+
@Test
89+
void shouldInstantiateZonePreferenceServiceInstanceListSupplier() {
90+
reactiveDiscoveryClientRunner
91+
.withPropertyValues(
92+
"spring.cloud.loadbalancer.configurations=zone-preference")
93+
.run(context -> {
94+
ServiceInstanceListSupplier supplier = context
95+
.getBean(ServiceInstanceListSupplier.class);
96+
then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class);
97+
ServiceInstanceListSupplier delegate = ((DelegatingServiceInstanceListSupplier) supplier)
98+
.getDelegate();
99+
then(delegate).isInstanceOf(
100+
ZonePreferenceServiceInstanceListSupplier.class);
101+
ServiceInstanceListSupplier secondDelegate = ((DelegatingServiceInstanceListSupplier) delegate)
102+
.getDelegate();
103+
then(secondDelegate).isInstanceOf(
104+
DiscoveryClientServiceInstanceListSupplier.class);
105+
});
106+
}
107+
108+
@Test
109+
void shouldInstantiateHealthCheckServiceInstanceListSupplier() {
110+
reactiveDiscoveryClientRunner.withUserConfiguration(TestConfig.class)
111+
.withPropertyValues(
112+
"spring.cloud.loadbalancer.configurations=health-check")
113+
.run(context -> {
114+
ServiceInstanceListSupplier supplier = context
115+
.getBean(ServiceInstanceListSupplier.class);
116+
then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class);
117+
ServiceInstanceListSupplier delegate = ((DelegatingServiceInstanceListSupplier) supplier)
118+
.getDelegate();
119+
then(delegate)
120+
.isInstanceOf(HealthCheckServiceInstanceListSupplier.class);
121+
ServiceInstanceListSupplier secondDelegate = ((DelegatingServiceInstanceListSupplier) delegate)
122+
.getDelegate();
123+
then(secondDelegate).isInstanceOf(
124+
DiscoveryClientServiceInstanceListSupplier.class);
125+
});
126+
}
127+
128+
@Test
129+
void shouldInstantiateDefaultBlockingServiceInstanceListSupplierWhenConfigurationsPropertyNotSet() {
130+
blockingDiscoveryClientRunner.run(context -> {
131+
ServiceInstanceListSupplier supplier = context
132+
.getBean(ServiceInstanceListSupplier.class);
133+
then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class);
134+
then(((DelegatingServiceInstanceListSupplier) supplier).getDelegate())
135+
.isInstanceOf(DiscoveryClientServiceInstanceListSupplier.class);
136+
});
137+
}
138+
139+
@Test
140+
void shouldInstantiateDefaultBlockingServiceInstanceListSupplier() {
141+
blockingDiscoveryClientRunner
142+
.withPropertyValues("spring.cloud.loadbalancer.configurations=default")
143+
.run(context -> {
144+
ServiceInstanceListSupplier supplier = context
145+
.getBean(ServiceInstanceListSupplier.class);
146+
then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class);
147+
then(((DelegatingServiceInstanceListSupplier) supplier).getDelegate())
148+
.isInstanceOf(
149+
DiscoveryClientServiceInstanceListSupplier.class);
150+
});
151+
}
152+
153+
@Test
154+
void shouldInstantiateServiceInstanceSupplierRegardlessOfConfigurationProperty() {
155+
reactiveDiscoveryClientRunner
156+
.withPropertyValues(
157+
"spring.cloud.loadbalancer.configurations=zone-preference")
158+
.run(context -> {
159+
ServiceInstanceSupplier supplier = context
160+
.getBean(ServiceInstanceSupplier.class);
161+
then(supplier).isInstanceOf(CachingServiceInstanceSupplier.class);
162+
});
163+
}
164+
165+
@Configuration
166+
protected static class TestConfig {
167+
168+
@Bean
169+
@LoadBalanced
170+
WebClient.Builder webClientBuilder() {
171+
return WebClient.builder();
172+
}
173+
174+
}
175+
176+
}

0 commit comments

Comments
 (0)