From 354a894606217fd466a30106c5ea736abcdf44ab Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Wed, 28 Jun 2023 12:28:44 +0200 Subject: [PATCH 01/12] Call get request on delegates (#1250) --- .../main/asciidoc/spring-cloud-commons.adoc | 26 +++++++++-- .../loadbalancer/LoadBalancerProperties.java | 43 +++++++++++++++++++ .../LoadBalancerClientConfiguration.java | 22 +++++----- ...DelegatingServiceInstanceListSupplier.java | 4 +- ...PreferenceServiceInstanceListSupplier.java | 19 ++++++++ .../ServiceInstanceListSupplierBuilder.java | 32 ++++++-------- ...PreferenceServiceInstanceListSupplier.java | 21 +++++++++ .../LoadBalancerClientConfigurationTests.java | 8 ++-- ...renceServiceInstanceListSupplierTests.java | 33 ++++++++++++-- ...rviceInstanceListSupplierBuilderTests.java | 6 +-- ...renceServiceInstanceListSupplierTests.java | 33 +++++++++++++- 11 files changed, 200 insertions(+), 47 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc index 97fc2423..ca20aa33 100644 --- a/docs/src/main/asciidoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -933,6 +933,11 @@ to `false`. WARNING: Although the basic, non-cached, implementation is useful for prototyping and testing, it's much less efficient than the cached versions, so we recommend always using the cached version in production. If the caching is already done by the `DiscoveryClient` implementation, for example `EurekaDiscoveryClient`, the load-balancer caching should be disabled to prevent double caching. +==== + +NOTE: When you create your own configuration, if you use `CachingServiceInstanceListSupplier` make sure to place it in the hierarchy directly after the supplier that retrieves the instances over the network, for example, `DiscoveryClientServiceInstanceListSupplier`, before any other filtering suppliers. + +==== === Zone-Based Load-Balancing To enable zone-based load-balancing, we provide the `ZonePreferenceServiceInstanceListSupplier`. @@ -950,7 +955,7 @@ If the zone is `null` or there are no instances within the same zone, it returns In order to use the zone-based load-balancing approach, you will have to instantiate a `ZonePreferenceServiceInstanceListSupplier` bean in a <>. We use delegates to work with `ServiceInstanceListSupplier` beans. -We suggest passing a `DiscoveryClientServiceInstanceListSupplier` delegate in the constructor of `ZonePreferenceServiceInstanceListSupplier` and, in turn, wrapping the latter with a `CachingServiceInstanceListSupplier` to leverage <>. +We suggest using a `DiscoveryClientServiceInstanceListSupplier` delegate, wrapping it with a `CachingServiceInstanceListSupplier` to leverage <>, and then passing the resulting bean in the constructor of `ZonePreferenceServiceInstanceListSupplier`. You can use this sample configuration to set it up: @@ -964,8 +969,8 @@ public class CustomLoadBalancerConfiguration { ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder() .withDiscoveryClient() + .withCaching() .withZonePreference() - .withCaching() .build(context); } } @@ -1026,6 +1031,12 @@ You can also pass your own `WebClient` or `RestTemplate` instance to be used for WARNING: `HealthCheckServiceInstanceListSupplier` has its own caching mechanism based on Reactor Flux `replay()`. Therefore, if it's being used, you may want to skip wrapping that supplier with `CachingServiceInstanceListSupplier`. +==== + +NOTE: When you create your own configuration, `HealthCheckServiceInstanceListSupplier`, make sure to place it in the hierarchy directly after the supplier that retrieves the instances over the network, for example, `DiscoveryClientServiceInstanceListSupplier`, before any other filtering suppliers. + +==== + === Same instance preference for LoadBalancer You can set up the LoadBalancer in such a way that it prefers the instance that was previously selected, if that instance is available. @@ -1110,8 +1121,8 @@ public class CustomLoadBalancerConfiguration { ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder() .withDiscoveryClient() + .withCaching() .withHints() - .withCaching() .build(context); } } @@ -1221,11 +1232,18 @@ public class MyConfiguration { } } ---- +==== NOTE: The classes you pass as `@LoadBalancerClient` or `@LoadBalancerClients` configuration arguments should either not be annotated with `@Configuration` or be outside component scan scope. ==== +==== + +NOTE: When you create your own configuration, if you use `CachingServiceInstanceListSupplier` or `HealthCheckServiceInstanceListSupplier`, makes sure to use one of them, not both, and make sure to place it in the hierarchy directly after the supplier that retrieves the instances over the network, for example, `DiscoveryClientServiceInstanceListSupplier`, before any other filtering suppliers. + +==== + [[loadbalancer-lifecycle]] === Spring Cloud LoadBalancer Lifecycle @@ -1301,6 +1319,8 @@ The per-client configuration properties work for most of the properties, apart f NOTE: For the properties where maps where already used, where you can specify a different value per-client without using the `clients` keyword (for example, `hints`, `health-check.path`), we have kept that behaviour in order to keep the library backwards compatible. It will be modified in the next major release. +NOTE: Starting with `3.1.7` in `2021.0.x` release train, `4.0.4` in `2022.0.x` release train and `4.1.0` in the `2023.0.x` release train, we have introduced the `callGetWithRequestOnDelegates` flag in `LoadBalancerProperties`. If this flag is set to `true`, `ServiceInstanceListSupplier#get(Request request)` method will be implemented to call `delegate.get(request)` in classes assignable from `DelegatingServiceInstanceListSupplier` that don't already implement that method, with the exclusion of `CachingServiceInstanceListSupplier` and `HealthCheckServiceInstanceListSupplier`, which should be placed in the instance supplier hierarchy directly after the supplier performing instance retrieval over the network, before any request-based filtering is done. For `3.1.x` and `4.0.x` the flag is set to `false` by default, and since `4.1.0` it's going to be set to `true` by default. + == Spring Cloud Circuit Breaker include::spring-cloud-circuitbreaker.adoc[leveloffset=+1] diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java index 4b719cc5..5537dde1 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java @@ -73,6 +73,19 @@ public class LoadBalancerProperties { */ private boolean useRawStatusCodeInResponseData; + /** + * If this flag is set to {@code true}, + * {@code ServiceInstanceListSupplier#get(Request request)} method will be implemented + * to call {@code delegate.get(request)} in classes assignable from + * {@code DelegatingServiceInstanceListSupplier} that don't already implement that + * method, with the exclusion of {@code CachingServiceInstanceListSupplier} and + * {@code HealthCheckServiceInstanceListSupplier}, which should be placed in the + * instance supplier hierarchy directly after the supplier performing instance + * retrieval over the network, before any request-based filtering is done. Note: in + * 4.1, this behaviour will become the default + */ + private boolean callGetWithRequestOnDelegates; + public HealthCheck getHealthCheck() { return healthCheck; } @@ -134,6 +147,36 @@ public class LoadBalancerProperties { this.useRawStatusCodeInResponseData = useRawStatusCodeInResponseData; } + /** + * If this flag is set to {@code true}, + * {@code ServiceInstanceListSupplier#get(Request request)} method will be implemented + * to call {@code delegate.get(request)} in classes assignable from + * {@code DelegatingServiceInstanceListSupplier} that don't already implement that + * method, with the exclusion of {@code CachingServiceInstanceListSupplier} and + * {@code HealthCheckServiceInstanceListSupplier}, which should be placed in the + * instance supplier hierarchy directly after the supplier performing instance + * retrieval over the network, before any request-based filtering is done. Note: in + * 4.1, this behaviour will become the default + */ + public boolean isCallGetWithRequestOnDelegates() { + return callGetWithRequestOnDelegates; + } + + /** + * If this flag is set to {@code true}, + * {@code ServiceInstanceListSupplier#get(Request request)} method will be implemented + * to call {@code delegate.get(request)} in classes assignable from + * {@code DelegatingServiceInstanceListSupplier} that don't already implement that + * method, with the exclusion of {@code CachingServiceInstanceListSupplier} and + * {@code HealthCheckServiceInstanceListSupplier}, which should be placed in the + * instance supplier hierarchy directly after the supplier performing instance + * retrieval over the network, before any request-based filtering is done. Note: in + * 4.1, this behaviour will become the default + */ + public void setCallGetWithRequestOnDelegates(boolean callGetWithRequestOnDelegates) { + this.callGetWithRequestOnDelegates = callGetWithRequestOnDelegates; + } + public static class StickySession { /** diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java index 7c2cc898..4f203f07 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java @@ -93,7 +93,7 @@ public class LoadBalancerClientConfiguration { @Conditional(ZonePreferenceConfigurationCondition.class) public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withDiscoveryClient().withZonePreference().withCaching() + return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().withZonePreference() .build(context); } @@ -119,8 +119,8 @@ public class LoadBalancerClientConfiguration { @Conditional(RequestBasedStickySessionConfigurationCondition.class) public ServiceInstanceListSupplier requestBasedStickySessionDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withDiscoveryClient().withRequestBasedStickySession() - .withCaching().build(context); + return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching() + .withRequestBasedStickySession().build(context); } @Bean @@ -129,8 +129,8 @@ public class LoadBalancerClientConfiguration { @Conditional(SameInstancePreferenceConfigurationCondition.class) public ServiceInstanceListSupplier sameInstancePreferenceServiceInstanceListSupplier( ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withDiscoveryClient().withSameInstancePreference() - .withCaching().build(context); + return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching() + .withSameInstancePreference().build(context); } } @@ -155,8 +155,8 @@ public class LoadBalancerClientConfiguration { @Conditional(ZonePreferenceConfigurationCondition.class) public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withZonePreference() - .withCaching().build(context); + return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching() + .withZonePreference().build(context); } @Bean @@ -175,8 +175,8 @@ public class LoadBalancerClientConfiguration { @Conditional(RequestBasedStickySessionConfigurationCondition.class) public ServiceInstanceListSupplier requestBasedStickySessionDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withRequestBasedStickySession() - .withCaching().build(context); + return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching() + .withRequestBasedStickySession().build(context); } @Bean @@ -185,8 +185,8 @@ public class LoadBalancerClientConfiguration { @Conditional(SameInstancePreferenceConfigurationCondition.class) public ServiceInstanceListSupplier sameInstancePreferenceServiceInstanceListSupplier( ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withSameInstancePreference() - .withCaching().build(context); + return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching() + .withSameInstancePreference().build(context); } } diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/DelegatingServiceInstanceListSupplier.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/DelegatingServiceInstanceListSupplier.java index 50ba6a18..af791aa4 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/DelegatingServiceInstanceListSupplier.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/DelegatingServiceInstanceListSupplier.java @@ -38,12 +38,12 @@ public abstract class DelegatingServiceInstanceListSupplier } public ServiceInstanceListSupplier getDelegate() { - return this.delegate; + return delegate; } @Override public String getServiceId() { - return this.delegate.getServiceId(); + return delegate.getServiceId(); } @Override diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplier.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplier.java index d198051a..8317d9d9 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplier.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplier.java @@ -24,6 +24,8 @@ import org.apache.commons.logging.LogFactory; import reactor.core.publisher.Flux; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.Request; +import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; /** * An implementation of {@link ServiceInstanceListSupplier} that selects the previously @@ -39,10 +41,19 @@ public class SameInstancePreferenceServiceInstanceListSupplier extends Delegatin private ServiceInstance previouslyReturnedInstance; + private boolean callGetWithRequestOnDelegates; + public SameInstancePreferenceServiceInstanceListSupplier(ServiceInstanceListSupplier delegate) { super(delegate); } + public SameInstancePreferenceServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, + ReactiveLoadBalancer.Factory loadBalancerClientFactory) { + super(delegate); + callGetWithRequestOnDelegates = loadBalancerClientFactory.getProperties(getServiceId()) + .isCallGetWithRequestOnDelegates(); + } + @Override public String getServiceId() { return delegate.getServiceId(); @@ -53,6 +64,14 @@ public class SameInstancePreferenceServiceInstanceListSupplier extends Delegatin return delegate.get().map(this::filteredBySameInstancePreference); } + @Override + public Flux> get(Request request) { + if (callGetWithRequestOnDelegates) { + return delegate.get(request).map(this::filteredBySameInstancePreference); + } + return get(); + } + private List filteredBySameInstancePreference(List serviceInstances) { if (previouslyReturnedInstance != null && serviceInstances.contains(previouslyReturnedInstance)) { if (LOG.isDebugEnabled()) { diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java index 6a19838e..0168d98b 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java @@ -57,8 +57,6 @@ public final class ServiceInstanceListSupplierBuilder { private Creator baseCreator; - private DelegateCreator cachingCreator; - private final List creators = new ArrayList<>(); ServiceInstanceListSupplierBuilder() { @@ -148,8 +146,10 @@ public final class ServiceInstanceListSupplierBuilder { * @return the {@link ServiceInstanceListSupplierBuilder} object */ public ServiceInstanceListSupplierBuilder withSameInstancePreference() { - DelegateCreator creator = (context, - delegate) -> new SameInstancePreferenceServiceInstanceListSupplier(delegate); + DelegateCreator creator = (context, delegate) -> { + LoadBalancerClientFactory loadBalancerClientFactory = context.getBean(LoadBalancerClientFactory.class); + return new SameInstancePreferenceServiceInstanceListSupplier(delegate, loadBalancerClientFactory); + }; this.creators.add(creator); return this; } @@ -191,8 +191,9 @@ public final class ServiceInstanceListSupplierBuilder { */ public ServiceInstanceListSupplierBuilder withZonePreference() { DelegateCreator creator = (context, delegate) -> { + LoadBalancerClientFactory loadBalancerClientFactory = context.getBean(LoadBalancerClientFactory.class); LoadBalancerZoneConfig zoneConfig = context.getBean(LoadBalancerZoneConfig.class); - return new ZonePreferenceServiceInstanceListSupplier(delegate, zoneConfig); + return new ZonePreferenceServiceInstanceListSupplier(delegate, zoneConfig, loadBalancerClientFactory); }; this.creators.add(creator); return this; @@ -206,8 +207,9 @@ public final class ServiceInstanceListSupplierBuilder { */ public ServiceInstanceListSupplierBuilder withZonePreference(String zoneName) { DelegateCreator creator = (context, delegate) -> { + LoadBalancerClientFactory loadBalancerClientFactory = context.getBean(LoadBalancerClientFactory.class); LoadBalancerZoneConfig zoneConfig = new LoadBalancerZoneConfig(zoneName); - return new ZonePreferenceServiceInstanceListSupplier(delegate, zoneConfig); + return new ZonePreferenceServiceInstanceListSupplier(delegate, zoneConfig, loadBalancerClientFactory); }; this.creators.add(creator); return this; @@ -228,19 +230,15 @@ public final class ServiceInstanceListSupplierBuilder { } /** - * If {@link LoadBalancerCacheManager} is available in the context, wraps created - * {@link ServiceInstanceListSupplier} hierarchy with a - * {@link CachingServiceInstanceListSupplier} instance to provide a caching mechanism - * for service instances. Uses {@link ObjectProvider} to lazily resolve + * If {@link LoadBalancerCacheManager} is available in the context, adds a + * {@link CachingServiceInstanceListSupplier} instance to the + * {@link ServiceInstanceListSupplier} hierarchy to provide a caching mechanism for + * service instances. Uses {@link ObjectProvider} to lazily resolve * {@link LoadBalancerCacheManager}. * @return the {@link ServiceInstanceListSupplierBuilder} object */ public ServiceInstanceListSupplierBuilder withCaching() { - if (cachingCreator != null && LOG.isWarnEnabled()) { - LOG.warn( - "Overriding a previously set cachingCreator with a CachingServiceInstanceListSupplier-based cachingCreator."); - } - this.cachingCreator = (context, delegate) -> { + DelegateCreator creator = (context, delegate) -> { ObjectProvider cacheManagerProvider = context .getBeanProvider(LoadBalancerCacheManager.class); if (cacheManagerProvider.getIfAvailable() != null) { @@ -251,6 +249,7 @@ public final class ServiceInstanceListSupplierBuilder { } return delegate; }; + creators.add(creator); return this; } @@ -297,9 +296,6 @@ public final class ServiceInstanceListSupplierBuilder { supplier = creator.apply(context, supplier); } - if (this.cachingCreator != null) { - supplier = this.cachingCreator.apply(context, supplier); - } return supplier; } diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplier.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplier.java index 83ad66a7..26f1c7da 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplier.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplier.java @@ -23,6 +23,8 @@ import java.util.Map; import reactor.core.publisher.Flux; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.Request; +import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; import org.springframework.cloud.loadbalancer.config.LoadBalancerZoneConfig; /** @@ -43,17 +45,36 @@ public class ZonePreferenceServiceInstanceListSupplier extends DelegatingService private String zone; + private boolean callGetWithRequestOnDelegates; + public ZonePreferenceServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, LoadBalancerZoneConfig zoneConfig) { super(delegate); this.zoneConfig = zoneConfig; } + public ZonePreferenceServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, + LoadBalancerZoneConfig zoneConfig, + ReactiveLoadBalancer.Factory loadBalancerClientFactory) { + super(delegate); + this.zoneConfig = zoneConfig; + callGetWithRequestOnDelegates = loadBalancerClientFactory.getProperties(getServiceId()) + .isCallGetWithRequestOnDelegates(); + } + @Override public Flux> get() { return getDelegate().get().map(this::filteredByZone); } + @Override + public Flux> get(Request request) { + if (callGetWithRequestOnDelegates) { + return getDelegate().get(request).map(this::filteredByZone); + } + return get(); + } + private List filteredByZone(List serviceInstances) { if (zone == null) { zone = zoneConfig.getZone(); diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationTests.java index 9ac93283..ebd12fea 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationTests.java @@ -91,10 +91,10 @@ class LoadBalancerClientConfigurationTests { reactiveDiscoveryClientRunner.withPropertyValues("spring.cloud.loadbalancer.configurations=zone-preference") .run(context -> { ServiceInstanceListSupplier supplier = context.getBean(ServiceInstanceListSupplier.class); - then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class); + then(supplier).isInstanceOf(ZonePreferenceServiceInstanceListSupplier.class); ServiceInstanceListSupplier delegate = ((DelegatingServiceInstanceListSupplier) supplier) .getDelegate(); - then(delegate).isInstanceOf(ZonePreferenceServiceInstanceListSupplier.class); + then(delegate).isInstanceOf(CachingServiceInstanceListSupplier.class); ServiceInstanceListSupplier secondDelegate = ((DelegatingServiceInstanceListSupplier) delegate) .getDelegate(); then(secondDelegate).isInstanceOf(DiscoveryClientServiceInstanceListSupplier.class); @@ -119,10 +119,10 @@ class LoadBalancerClientConfigurationTests { .withPropertyValues("spring.cloud.loadbalancer.configurations=request-based-sticky-session") .run(context -> { ServiceInstanceListSupplier supplier = context.getBean(ServiceInstanceListSupplier.class); - then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class); + then(supplier).isInstanceOf(RequestBasedStickySessionServiceInstanceListSupplier.class); ServiceInstanceListSupplier delegate = ((DelegatingServiceInstanceListSupplier) supplier) .getDelegate(); - then(delegate).isInstanceOf(RequestBasedStickySessionServiceInstanceListSupplier.class); + then(delegate).isInstanceOf(CachingServiceInstanceListSupplier.class); ServiceInstanceListSupplier secondDelegate = ((DelegatingServiceInstanceListSupplier) delegate) .getDelegate(); then(secondDelegate).isInstanceOf(DiscoveryClientServiceInstanceListSupplier.class); diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplierTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplierTests.java index fd66a251..bf6e260b 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplierTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplierTests.java @@ -19,13 +19,20 @@ package org.springframework.cloud.loadbalancer.core; import java.util.Arrays; import java.util.List; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.DefaultRequest; +import org.springframework.cloud.client.loadbalancer.DefaultRequestContext; +import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.client.loadbalancer.Request; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -39,8 +46,9 @@ class SameInstancePreferenceServiceInstanceListSupplierTests { private final DiscoveryClientServiceInstanceListSupplier delegate = mock( DiscoveryClientServiceInstanceListSupplier.class); - private final SameInstancePreferenceServiceInstanceListSupplier supplier = new SameInstancePreferenceServiceInstanceListSupplier( - delegate); + private final LoadBalancerClientFactory loadBalancerClientFactory = mock(LoadBalancerClientFactory.class); + + private SameInstancePreferenceServiceInstanceListSupplier supplier; private final ServiceInstance first = serviceInstance("test-1"); @@ -48,6 +56,14 @@ class SameInstancePreferenceServiceInstanceListSupplierTests { private final ServiceInstance third = serviceInstance("test-3"); + @BeforeEach + void setUp() { + LoadBalancerProperties properties = new LoadBalancerProperties(); + properties.setCallGetWithRequestOnDelegates(true); + when(loadBalancerClientFactory.getProperties(any())).thenReturn(properties); + supplier = new SameInstancePreferenceServiceInstanceListSupplier(delegate, loadBalancerClientFactory); + } + @Test void shouldReturnPreviouslySelectedInstanceIfAvailable() { when(delegate.get()).thenReturn(Flux.just(Arrays.asList(first, second, third))); @@ -69,7 +85,7 @@ class SameInstancePreferenceServiceInstanceListSupplierTests { } @Test - void shouldReturnAllInstancesFromDelegateIfPreviouslySelectedInstanceIfAvailable() { + void shouldReturnAllInstancesFromDelegateIfPreviouslySelectedInstanceIsNotAvailable() { when(delegate.get()).thenReturn(Flux.just(Arrays.asList(second, third))); supplier.selectedServiceInstance(first); @@ -78,6 +94,17 @@ class SameInstancePreferenceServiceInstanceListSupplierTests { assertThat(instances).hasSize(2); } + @Test + void shouldCallGetRequestOnDelegate() { + Request request = new DefaultRequest<>(new DefaultRequestContext()); + when(delegate.get()).thenReturn(Flux.just(Arrays.asList(first, second, third))); + when(delegate.get(request)).thenReturn(Flux.just(Arrays.asList(first, second))); + + List instances = supplier.get(request).blockFirst(); + + assertThat(instances).hasSize(2); + } + private DefaultServiceInstance serviceInstance(String instanceId) { return new DefaultServiceInstance(instanceId, "test", "http://test.test", 9080, false); } diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilderTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilderTests.java index 8793b8ee..7b958dd2 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilderTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilderTests.java @@ -37,11 +37,9 @@ public class ServiceInstanceListSupplierBuilderTests { public void testBuilder() { new ApplicationContextRunner().withUserConfiguration(CacheTestConfig.class).run(context -> { ServiceInstanceListSupplier supplier = ServiceInstanceListSupplier.builder().withDiscoveryClient() - .withHealthChecks().withCaching().build(context); - assertThat(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class); + .withHealthChecks().build(context); + assertThat(supplier).isInstanceOf(HealthCheckServiceInstanceListSupplier.class); DelegatingServiceInstanceListSupplier delegating = (DelegatingServiceInstanceListSupplier) supplier; - assertThat(delegating.getDelegate()).isInstanceOf(HealthCheckServiceInstanceListSupplier.class); - delegating = (DelegatingServiceInstanceListSupplier) delegating.getDelegate(); assertThat(delegating.getDelegate()).isInstanceOf(DiscoveryClientServiceInstanceListSupplier.class); }); } diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplierTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplierTests.java index 4fe7d39f..238cec0a 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplierTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplierTests.java @@ -22,15 +22,22 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.DefaultRequest; +import org.springframework.cloud.client.loadbalancer.DefaultRequestContext; +import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.client.loadbalancer.Request; import org.springframework.cloud.loadbalancer.config.LoadBalancerZoneConfig; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -46,8 +53,9 @@ class ZonePreferenceServiceInstanceListSupplierTests { private final LoadBalancerZoneConfig zoneConfig = new LoadBalancerZoneConfig(null); - private final ZonePreferenceServiceInstanceListSupplier supplier = new ZonePreferenceServiceInstanceListSupplier( - delegate, zoneConfig); + private ZonePreferenceServiceInstanceListSupplier supplier; + + private final LoadBalancerClientFactory loadBalancerClientFactory = mock(LoadBalancerClientFactory.class); private final ServiceInstance first = serviceInstance("test-1", buildZoneMetadata("zone1")); @@ -59,6 +67,14 @@ class ZonePreferenceServiceInstanceListSupplierTests { private final ServiceInstance fifth = serviceInstance("test-5", buildZoneMetadata(null)); + @BeforeEach + void setUp() { + LoadBalancerProperties properties = new LoadBalancerProperties(); + properties.setCallGetWithRequestOnDelegates(true); + when(loadBalancerClientFactory.getProperties(any())).thenReturn(properties); + supplier = new ZonePreferenceServiceInstanceListSupplier(delegate, zoneConfig, loadBalancerClientFactory); + } + @Test void shouldFilterInstancesByZone() { zoneConfig.setZone("zone1"); @@ -73,6 +89,19 @@ class ZonePreferenceServiceInstanceListSupplierTests { assertThat(filtered).doesNotContain(fifth); } + @Test + void shouldCallGetRequestOnDelegate() { + zoneConfig.setZone("zone1"); + Request request = new DefaultRequest<>(new DefaultRequestContext()); + when(delegate.get()).thenReturn(Flux.just(Arrays.asList(first, second, third, fourth, fifth))); + when(delegate.get(request)).thenReturn(Flux.just(Arrays.asList(first, third, fourth, fifth))); + + List filtered = supplier.get(request).blockFirst(); + + assertThat(filtered).hasSize(1); + assertThat(filtered).containsOnly(first); + } + @Test void shouldReturnAllInstancesIfNoZoneInstances() { zoneConfig.setZone("zone1"); From d36062b8bb51b6cf39e1fa3065966f1d0c33f3bf Mon Sep 17 00:00:00 2001 From: Olga MaciaszekSharma Date: Wed, 28 Jun 2023 13:46:49 +0200 Subject: [PATCH 02/12] Update copyright and fix docs. --- docs/src/main/asciidoc/spring-cloud-commons.adoc | 2 +- .../cloud/client/loadbalancer/LoadBalancerProperties.java | 2 +- .../core/DelegatingServiceInstanceListSupplier.java | 2 +- .../core/SameInstancePreferenceServiceInstanceListSupplier.java | 2 +- .../loadbalancer/core/ServiceInstanceListSupplierBuilder.java | 2 +- .../core/ZonePreferenceServiceInstanceListSupplier.java | 2 +- .../SameInstancePreferenceServiceInstanceListSupplierTests.java | 2 +- .../core/ServiceInstanceListSupplierBuilderTests.java | 2 +- .../core/ZonePreferenceServiceInstanceListSupplierTests.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc index ca20aa33..893341f9 100644 --- a/docs/src/main/asciidoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -1319,7 +1319,7 @@ The per-client configuration properties work for most of the properties, apart f NOTE: For the properties where maps where already used, where you can specify a different value per-client without using the `clients` keyword (for example, `hints`, `health-check.path`), we have kept that behaviour in order to keep the library backwards compatible. It will be modified in the next major release. -NOTE: Starting with `3.1.7` in `2021.0.x` release train, `4.0.4` in `2022.0.x` release train and `4.1.0` in the `2023.0.x` release train, we have introduced the `callGetWithRequestOnDelegates` flag in `LoadBalancerProperties`. If this flag is set to `true`, `ServiceInstanceListSupplier#get(Request request)` method will be implemented to call `delegate.get(request)` in classes assignable from `DelegatingServiceInstanceListSupplier` that don't already implement that method, with the exclusion of `CachingServiceInstanceListSupplier` and `HealthCheckServiceInstanceListSupplier`, which should be placed in the instance supplier hierarchy directly after the supplier performing instance retrieval over the network, before any request-based filtering is done. For `3.1.x` and `4.0.x` the flag is set to `false` by default, and since `4.1.0` it's going to be set to `true` by default. +NOTE: Starting with `3.1.7`, we have introduced the `callGetWithRequestOnDelegates` flag in `LoadBalancerProperties`. If this flag is set to `true`, `ServiceInstanceListSupplier#get(Request request)` method will be implemented to call `delegate.get(request)` in classes assignable from `DelegatingServiceInstanceListSupplier` that don't already implement that method, with the exclusion of `CachingServiceInstanceListSupplier` and `HealthCheckServiceInstanceListSupplier`, which should be placed in the instance supplier hierarchy directly after the supplier performing instance retrieval over the network, before any request-based filtering is done. For `3.1.x` the flag is set to `false` by default, however, since `4.1.0` it's going to be set to `true` by default. == Spring Cloud Circuit Breaker diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java index 5537dde1..d600e081 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2023 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. diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/DelegatingServiceInstanceListSupplier.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/DelegatingServiceInstanceListSupplier.java index af791aa4..aaf17218 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/DelegatingServiceInstanceListSupplier.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/DelegatingServiceInstanceListSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2023 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. diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplier.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplier.java index 8317d9d9..bf504fad 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplier.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2023 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. diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java index 0168d98b..0dcd4095 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2023 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. diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplier.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplier.java index 26f1c7da..dafbbad7 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplier.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2023 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. diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplierTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplierTests.java index bf6e260b..2563db25 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplierTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/SameInstancePreferenceServiceInstanceListSupplierTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2023 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. diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilderTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilderTests.java index 7b958dd2..ecb86c02 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilderTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2023 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. diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplierTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplierTests.java index 238cec0a..f04c9ba8 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplierTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/ZonePreferenceServiceInstanceListSupplierTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2023 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. From e4e56e93cfdb007df0f089647ae40ce6864d30b3 Mon Sep 17 00:00:00 2001 From: Olga MaciaszekSharma Date: Wed, 28 Jun 2023 14:30:15 +0200 Subject: [PATCH 03/12] Call `get(Request request)` on delegates in WeightedServiceInstanceListSupplier. --- .../LoadBalancerClientConfiguration.java | 4 +-- .../ServiceInstanceListSupplierBuilder.java | 13 ++++++-- .../WeightedServiceInstanceListSupplier.java | 31 +++++++++++++++-- .../LoadBalancerClientConfigurationTests.java | 8 ++--- ...ghtedServiceInstanceListSupplierTests.java | 33 ++++++++++++++++++- 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java index ea9cd772..f0aae50c 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java @@ -139,7 +139,7 @@ public class LoadBalancerClientConfiguration { @ConditionalOnMissingBean @Conditional(WeightedConfigurationCondition.class) public ServiceInstanceListSupplier weightedServiceInstanceListSupplier(ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withDiscoveryClient().withWeighted().withCaching() + return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().withWeighted() .build(context); } @@ -204,7 +204,7 @@ public class LoadBalancerClientConfiguration { @ConditionalOnMissingBean @Conditional(WeightedConfigurationCondition.class) public ServiceInstanceListSupplier weightedServiceInstanceListSupplier(ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withWeighted().withCaching() + return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching().withWeighted() .build(context); } diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java index 7906638a..74ee2e38 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplierBuilder.java @@ -116,7 +116,11 @@ public final class ServiceInstanceListSupplierBuilder { * @return the {@link ServiceInstanceListSupplierBuilder} object */ public ServiceInstanceListSupplierBuilder withWeighted() { - DelegateCreator creator = (context, delegate) -> new WeightedServiceInstanceListSupplier(delegate); + DelegateCreator creator = (context, delegate) -> { + ReactiveLoadBalancer.Factory loadBalancerClientFactory = context + .getBean(LoadBalancerClientFactory.class); + return new WeightedServiceInstanceListSupplier(delegate, loadBalancerClientFactory); + }; this.creators.add(creator); return this; } @@ -129,8 +133,11 @@ public final class ServiceInstanceListSupplierBuilder { * @return the {@link ServiceInstanceListSupplierBuilder} object */ public ServiceInstanceListSupplierBuilder withWeighted(WeightFunction weightFunction) { - DelegateCreator creator = (context, delegate) -> new WeightedServiceInstanceListSupplier(delegate, - weightFunction); + DelegateCreator creator = (context, delegate) -> { + ReactiveLoadBalancer.Factory loadBalancerClientFactory = context + .getBean(LoadBalancerClientFactory.class); + return new WeightedServiceInstanceListSupplier(delegate, weightFunction, loadBalancerClientFactory); + }; this.creators.add(creator); return this; } diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/WeightedServiceInstanceListSupplier.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/WeightedServiceInstanceListSupplier.java index 527e6173..172038b5 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/WeightedServiceInstanceListSupplier.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/WeightedServiceInstanceListSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2023 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. @@ -24,12 +24,15 @@ import org.apache.commons.logging.LogFactory; import reactor.core.publisher.Flux; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.Request; +import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; /** * A {@link ServiceInstanceListSupplier} implementation that uses weights to expand the * instances provided by delegate. * * @author Zhuozhi Ji + * @author Olga Maciaszek-Sharma */ public class WeightedServiceInstanceListSupplier extends DelegatingServiceInstanceListSupplier { @@ -41,9 +44,10 @@ public class WeightedServiceInstanceListSupplier extends DelegatingServiceInstan private final WeightFunction weightFunction; + private boolean callGetWithRequestOnDelegates; + public WeightedServiceInstanceListSupplier(ServiceInstanceListSupplier delegate) { - super(delegate); - this.weightFunction = WeightedServiceInstanceListSupplier::metadataWeightFunction; + this(delegate, WeightedServiceInstanceListSupplier::metadataWeightFunction); } public WeightedServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, WeightFunction weightFunction) { @@ -51,11 +55,32 @@ public class WeightedServiceInstanceListSupplier extends DelegatingServiceInstan this.weightFunction = weightFunction; } + public WeightedServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, + ReactiveLoadBalancer.Factory loadBalancerClientFactory) { + this(delegate, WeightedServiceInstanceListSupplier::metadataWeightFunction, loadBalancerClientFactory); + } + + public WeightedServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, WeightFunction weightFunction, + ReactiveLoadBalancer.Factory loadBalancerClientFactory) { + super(delegate); + this.weightFunction = weightFunction; + callGetWithRequestOnDelegates = loadBalancerClientFactory.getProperties(getServiceId()) + .isCallGetWithRequestOnDelegates(); + } + @Override public Flux> get() { return delegate.get().map(this::expandByWeight); } + @Override + public Flux> get(Request request) { + if (callGetWithRequestOnDelegates) { + return delegate.get(request).map(this::expandByWeight); + } + return get(); + } + private List expandByWeight(List instances) { if (instances.size() == 0) { return instances; diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationTests.java index 858d5ce4..eda9dc1c 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationTests.java @@ -120,10 +120,10 @@ class LoadBalancerClientConfigurationTests { reactiveDiscoveryClientRunner.withUserConfiguration(TestConfig.class) .withPropertyValues("spring.cloud.loadbalancer.configurations=weighted").run(context -> { ServiceInstanceListSupplier supplier = context.getBean(ServiceInstanceListSupplier.class); - then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class); + then(supplier).isInstanceOf(WeightedServiceInstanceListSupplier.class); ServiceInstanceListSupplier delegate = ((DelegatingServiceInstanceListSupplier) supplier) .getDelegate(); - then(delegate).isInstanceOf(WeightedServiceInstanceListSupplier.class); + then(delegate).isInstanceOf(CachingServiceInstanceListSupplier.class); ServiceInstanceListSupplier secondDelegate = ((DelegatingServiceInstanceListSupplier) delegate) .getDelegate(); then(secondDelegate).isInstanceOf(DiscoveryClientServiceInstanceListSupplier.class); @@ -207,10 +207,10 @@ class LoadBalancerClientConfigurationTests { blockingDiscoveryClientRunner.withUserConfiguration(RestTemplateTestConfig.class) .withPropertyValues("spring.cloud.loadbalancer.configurations=weighted").run(context -> { ServiceInstanceListSupplier supplier = context.getBean(ServiceInstanceListSupplier.class); - then(supplier).isInstanceOf(CachingServiceInstanceListSupplier.class); + then(supplier).isInstanceOf(WeightedServiceInstanceListSupplier.class); ServiceInstanceListSupplier delegate = ((DelegatingServiceInstanceListSupplier) supplier) .getDelegate(); - then(delegate).isInstanceOf(WeightedServiceInstanceListSupplier.class); + then(delegate).isInstanceOf(CachingServiceInstanceListSupplier.class); then(((DelegatingServiceInstanceListSupplier) delegate).getDelegate()) .isInstanceOf(DiscoveryClientServiceInstanceListSupplier.class); }); diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/WeightedServiceInstanceListSupplierTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/WeightedServiceInstanceListSupplierTests.java index 9bd925e2..58c00682 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/WeightedServiceInstanceListSupplierTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/WeightedServiceInstanceListSupplierTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2023 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. @@ -29,9 +29,15 @@ import reactor.core.publisher.Flux; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.DefaultRequest; +import org.springframework.cloud.client.loadbalancer.DefaultRequestContext; +import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.client.loadbalancer.Request; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import static java.util.stream.Collectors.summingInt; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.springframework.cloud.loadbalancer.core.WeightedServiceInstanceListSupplier.DEFAULT_WEIGHT; @@ -40,6 +46,7 @@ import static org.springframework.cloud.loadbalancer.core.WeightedServiceInstanc * Tests for {@link WeightedServiceInstanceListSupplier}. * * @author Zhuozhi Ji + * @author Olga Maciaszek-Sharma */ class WeightedServiceInstanceListSupplierTests { @@ -177,6 +184,30 @@ class WeightedServiceInstanceListSupplierTests { assertThat(counter).containsEntry("test-3", DEFAULT_WEIGHT); } + @Test + void shouldCallGetRequestOnDelegate() { + LoadBalancerClientFactory loadBalancerClientFactory = mock(LoadBalancerClientFactory.class); + LoadBalancerProperties properties = new LoadBalancerProperties(); + properties.setCallGetWithRequestOnDelegates(true); + when(loadBalancerClientFactory.getProperties(any())).thenReturn(properties); + ServiceInstance one = serviceInstance("test-1", Collections.emptyMap()); + ServiceInstance two = serviceInstance("test-2", Collections.emptyMap()); + ServiceInstance three = serviceInstance("test-3", buildWeightMetadata(3)); + Request request = new DefaultRequest<>(new DefaultRequestContext()); + + when(delegate.get()).thenReturn(Flux.just(Arrays.asList(one, two, three))); + when(delegate.get(request)).thenReturn(Flux.just(Arrays.asList(one, two))); + WeightedServiceInstanceListSupplier supplier = new WeightedServiceInstanceListSupplier(delegate, + loadBalancerClientFactory); + + List serviceInstances = Objects.requireNonNull(supplier.get(request).blockFirst()); + Map counter = serviceInstances.stream() + .collect(Collectors.groupingBy(ServiceInstance::getInstanceId, summingInt(e -> 1))); + assertThat(counter).containsEntry("test-1", DEFAULT_WEIGHT); + assertThat(counter).containsEntry("test-2", DEFAULT_WEIGHT); + assertThat(counter).doesNotContainEntry("test-3", 3); + } + private ServiceInstance serviceInstance(String instanceId, Map metadata) { return new DefaultServiceInstance(instanceId, "test", "localhost", 8080, false, metadata); } From 4c639f1cf1e2faa034d12424fa2f3a610d652f75 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Thu, 29 Jun 2023 10:31:29 +0000 Subject: [PATCH 04/12] Update SNAPSHOT to 3.1.7 --- docs/pom.xml | 2 +- docs/src/main/asciidoc/_configprops.adoc | 1 + pom.xml | 4 ++-- spring-cloud-commons-dependencies/pom.xml | 4 ++-- spring-cloud-commons/pom.xml | 2 +- spring-cloud-context-integration-tests/pom.xml | 2 +- spring-cloud-context-webflux-integration-tests/pom.xml | 2 +- spring-cloud-context/pom.xml | 2 +- spring-cloud-loadbalancer/pom.xml | 2 +- spring-cloud-starter-bootstrap/pom.xml | 2 +- spring-cloud-starter-loadbalancer/pom.xml | 2 +- spring-cloud-starter/pom.xml | 2 +- spring-cloud-test-support/pom.xml | 2 +- 13 files changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 808e9479..409915ff 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 jar Spring Cloud Commons Docs diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 93facf98..b58bcd80 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -30,6 +30,7 @@ |spring.cloud.loadbalancer.cache.capacity | `+++256+++` | Initial cache capacity expressed as int. |spring.cloud.loadbalancer.cache.enabled | `+++true+++` | Enables Spring Cloud LoadBalancer caching mechanism. |spring.cloud.loadbalancer.cache.ttl | `+++35s+++` | Time To Live - time counted from writing of the record, after which cache entries are expired, expressed as a {@link Duration}. The property {@link String} has to be in keeping with the appropriate syntax as specified in Spring Boot StringToDurationConverter. @see StringToDurationConverter.java +|spring.cloud.loadbalancer.call-get-with-request-on-delegates | `+++false+++` | If this flag is set to {@code true}, {@code ServiceInstanceListSupplier#get(Request request)} method will be implemented to call {@code delegate.get(request)} in classes assignable from {@code DelegatingServiceInstanceListSupplier} that don't already implement that method, with the exclusion of {@code CachingServiceInstanceListSupplier} and {@code HealthCheckServiceInstanceListSupplier}, which should be placed in the instance supplier hierarchy directly after the supplier performing instance retrieval over the network, before any request-based filtering is done. Note: in 4.1, this behaviour will become the default |spring.cloud.loadbalancer.clients | | |spring.cloud.loadbalancer.configurations | `+++default+++` | Enables a predefined LoadBalancer configuration. |spring.cloud.loadbalancer.enabled | `+++true+++` | Enables Spring Cloud LoadBalancer. diff --git a/pom.xml b/pom.xml index 8e338f67..ea9df671 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 pom Spring Cloud Commons Parent Spring Cloud Commons Parent @@ -13,7 +13,7 @@ org.springframework.cloud spring-cloud-build - 3.1.8-SNAPSHOT + 3.1.8 diff --git a/spring-cloud-commons-dependencies/pom.xml b/spring-cloud-commons-dependencies/pom.xml index 0058d81c..2aa66ef1 100644 --- a/spring-cloud-commons-dependencies/pom.xml +++ b/spring-cloud-commons-dependencies/pom.xml @@ -6,11 +6,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 3.1.8-SNAPSHOT + 3.1.8 spring-cloud-commons-dependencies - 3.1.7-SNAPSHOT + 3.1.7 pom spring-cloud-commons-dependencies Spring Cloud Commons Dependencies diff --git a/spring-cloud-commons/pom.xml b/spring-cloud-commons/pom.xml index 44e95136..4de99bfb 100644 --- a/spring-cloud-commons/pom.xml +++ b/spring-cloud-commons/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 .. spring-cloud-commons diff --git a/spring-cloud-context-integration-tests/pom.xml b/spring-cloud-context-integration-tests/pom.xml index 07b56be6..4de23aaf 100644 --- a/spring-cloud-context-integration-tests/pom.xml +++ b/spring-cloud-context-integration-tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 .. spring-cloud-context-integration-tests diff --git a/spring-cloud-context-webflux-integration-tests/pom.xml b/spring-cloud-context-webflux-integration-tests/pom.xml index 8262f599..e341ae17 100644 --- a/spring-cloud-context-webflux-integration-tests/pom.xml +++ b/spring-cloud-context-webflux-integration-tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 .. spring-cloud-context-webflux-integration-tests diff --git a/spring-cloud-context/pom.xml b/spring-cloud-context/pom.xml index 6042bdff..7a9a5a03 100644 --- a/spring-cloud-context/pom.xml +++ b/spring-cloud-context/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 .. spring-cloud-context diff --git a/spring-cloud-loadbalancer/pom.xml b/spring-cloud-loadbalancer/pom.xml index e5b19aa6..b238c4ae 100644 --- a/spring-cloud-loadbalancer/pom.xml +++ b/spring-cloud-loadbalancer/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 .. spring-cloud-loadbalancer diff --git a/spring-cloud-starter-bootstrap/pom.xml b/spring-cloud-starter-bootstrap/pom.xml index 6bb820f9..d3d825c0 100644 --- a/spring-cloud-starter-bootstrap/pom.xml +++ b/spring-cloud-starter-bootstrap/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 .. jar diff --git a/spring-cloud-starter-loadbalancer/pom.xml b/spring-cloud-starter-loadbalancer/pom.xml index 3e4269b6..cc4c9e66 100644 --- a/spring-cloud-starter-loadbalancer/pom.xml +++ b/spring-cloud-starter-loadbalancer/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 .. 4.0.0 diff --git a/spring-cloud-starter/pom.xml b/spring-cloud-starter/pom.xml index 2e2f2d47..ba2ee7d9 100644 --- a/spring-cloud-starter/pom.xml +++ b/spring-cloud-starter/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 spring-cloud-starter spring-cloud-starter diff --git a/spring-cloud-test-support/pom.xml b/spring-cloud-test-support/pom.xml index daac488c..aba01b19 100644 --- a/spring-cloud-test-support/pom.xml +++ b/spring-cloud-test-support/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.7 .. spring-cloud-test-support From 7a9bba08ed8fddfccfac9eba08b239910069e3a4 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Thu, 29 Jun 2023 10:33:38 +0000 Subject: [PATCH 05/12] Going back to snapshots --- docs/pom.xml | 2 +- docs/src/main/asciidoc/_configprops.adoc | 1 - pom.xml | 4 ++-- spring-cloud-commons-dependencies/pom.xml | 4 ++-- spring-cloud-commons/pom.xml | 2 +- spring-cloud-context-integration-tests/pom.xml | 2 +- spring-cloud-context-webflux-integration-tests/pom.xml | 2 +- spring-cloud-context/pom.xml | 2 +- spring-cloud-loadbalancer/pom.xml | 2 +- spring-cloud-starter-bootstrap/pom.xml | 2 +- spring-cloud-starter-loadbalancer/pom.xml | 2 +- spring-cloud-starter/pom.xml | 2 +- spring-cloud-test-support/pom.xml | 2 +- 13 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 409915ff..808e9479 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT jar Spring Cloud Commons Docs diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index b58bcd80..93facf98 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -30,7 +30,6 @@ |spring.cloud.loadbalancer.cache.capacity | `+++256+++` | Initial cache capacity expressed as int. |spring.cloud.loadbalancer.cache.enabled | `+++true+++` | Enables Spring Cloud LoadBalancer caching mechanism. |spring.cloud.loadbalancer.cache.ttl | `+++35s+++` | Time To Live - time counted from writing of the record, after which cache entries are expired, expressed as a {@link Duration}. The property {@link String} has to be in keeping with the appropriate syntax as specified in Spring Boot StringToDurationConverter. @see StringToDurationConverter.java -|spring.cloud.loadbalancer.call-get-with-request-on-delegates | `+++false+++` | If this flag is set to {@code true}, {@code ServiceInstanceListSupplier#get(Request request)} method will be implemented to call {@code delegate.get(request)} in classes assignable from {@code DelegatingServiceInstanceListSupplier} that don't already implement that method, with the exclusion of {@code CachingServiceInstanceListSupplier} and {@code HealthCheckServiceInstanceListSupplier}, which should be placed in the instance supplier hierarchy directly after the supplier performing instance retrieval over the network, before any request-based filtering is done. Note: in 4.1, this behaviour will become the default |spring.cloud.loadbalancer.clients | | |spring.cloud.loadbalancer.configurations | `+++default+++` | Enables a predefined LoadBalancer configuration. |spring.cloud.loadbalancer.enabled | `+++true+++` | Enables Spring Cloud LoadBalancer. diff --git a/pom.xml b/pom.xml index ea9df671..8e338f67 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT pom Spring Cloud Commons Parent Spring Cloud Commons Parent @@ -13,7 +13,7 @@ org.springframework.cloud spring-cloud-build - 3.1.8 + 3.1.8-SNAPSHOT diff --git a/spring-cloud-commons-dependencies/pom.xml b/spring-cloud-commons-dependencies/pom.xml index 2aa66ef1..0058d81c 100644 --- a/spring-cloud-commons-dependencies/pom.xml +++ b/spring-cloud-commons-dependencies/pom.xml @@ -6,11 +6,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 3.1.8 + 3.1.8-SNAPSHOT spring-cloud-commons-dependencies - 3.1.7 + 3.1.7-SNAPSHOT pom spring-cloud-commons-dependencies Spring Cloud Commons Dependencies diff --git a/spring-cloud-commons/pom.xml b/spring-cloud-commons/pom.xml index 4de99bfb..44e95136 100644 --- a/spring-cloud-commons/pom.xml +++ b/spring-cloud-commons/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT .. spring-cloud-commons diff --git a/spring-cloud-context-integration-tests/pom.xml b/spring-cloud-context-integration-tests/pom.xml index 4de23aaf..07b56be6 100644 --- a/spring-cloud-context-integration-tests/pom.xml +++ b/spring-cloud-context-integration-tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT .. spring-cloud-context-integration-tests diff --git a/spring-cloud-context-webflux-integration-tests/pom.xml b/spring-cloud-context-webflux-integration-tests/pom.xml index e341ae17..8262f599 100644 --- a/spring-cloud-context-webflux-integration-tests/pom.xml +++ b/spring-cloud-context-webflux-integration-tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT .. spring-cloud-context-webflux-integration-tests diff --git a/spring-cloud-context/pom.xml b/spring-cloud-context/pom.xml index 7a9a5a03..6042bdff 100644 --- a/spring-cloud-context/pom.xml +++ b/spring-cloud-context/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT .. spring-cloud-context diff --git a/spring-cloud-loadbalancer/pom.xml b/spring-cloud-loadbalancer/pom.xml index b238c4ae..e5b19aa6 100644 --- a/spring-cloud-loadbalancer/pom.xml +++ b/spring-cloud-loadbalancer/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT .. spring-cloud-loadbalancer diff --git a/spring-cloud-starter-bootstrap/pom.xml b/spring-cloud-starter-bootstrap/pom.xml index d3d825c0..6bb820f9 100644 --- a/spring-cloud-starter-bootstrap/pom.xml +++ b/spring-cloud-starter-bootstrap/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT .. jar diff --git a/spring-cloud-starter-loadbalancer/pom.xml b/spring-cloud-starter-loadbalancer/pom.xml index cc4c9e66..3e4269b6 100644 --- a/spring-cloud-starter-loadbalancer/pom.xml +++ b/spring-cloud-starter-loadbalancer/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT .. 4.0.0 diff --git a/spring-cloud-starter/pom.xml b/spring-cloud-starter/pom.xml index ba2ee7d9..2e2f2d47 100644 --- a/spring-cloud-starter/pom.xml +++ b/spring-cloud-starter/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT spring-cloud-starter spring-cloud-starter diff --git a/spring-cloud-test-support/pom.xml b/spring-cloud-test-support/pom.xml index aba01b19..daac488c 100644 --- a/spring-cloud-test-support/pom.xml +++ b/spring-cloud-test-support/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7 + 3.1.7-SNAPSHOT .. spring-cloud-test-support From d53f45d1f73477eb1f7eeb69b284e2dfb4300eca Mon Sep 17 00:00:00 2001 From: buildmaster Date: Thu, 29 Jun 2023 10:33:39 +0000 Subject: [PATCH 06/12] Bumping versions to 3.1.8-SNAPSHOT after release --- docs/pom.xml | 2 +- pom.xml | 4 ++-- spring-cloud-commons-dependencies/pom.xml | 4 ++-- spring-cloud-commons/pom.xml | 2 +- spring-cloud-context-integration-tests/pom.xml | 2 +- spring-cloud-context-webflux-integration-tests/pom.xml | 2 +- spring-cloud-context/pom.xml | 2 +- spring-cloud-loadbalancer/pom.xml | 2 +- spring-cloud-starter-bootstrap/pom.xml | 2 +- spring-cloud-starter-loadbalancer/pom.xml | 2 +- spring-cloud-starter/pom.xml | 2 +- spring-cloud-test-support/pom.xml | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 808e9479..96b1171f 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT jar Spring Cloud Commons Docs diff --git a/pom.xml b/pom.xml index 8e338f67..a93d983c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT pom Spring Cloud Commons Parent Spring Cloud Commons Parent @@ -13,7 +13,7 @@ org.springframework.cloud spring-cloud-build - 3.1.8-SNAPSHOT + 3.1.9-SNAPSHOT diff --git a/spring-cloud-commons-dependencies/pom.xml b/spring-cloud-commons-dependencies/pom.xml index 0058d81c..a4a97651 100644 --- a/spring-cloud-commons-dependencies/pom.xml +++ b/spring-cloud-commons-dependencies/pom.xml @@ -6,11 +6,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 3.1.8-SNAPSHOT + 3.1.9-SNAPSHOT spring-cloud-commons-dependencies - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT pom spring-cloud-commons-dependencies Spring Cloud Commons Dependencies diff --git a/spring-cloud-commons/pom.xml b/spring-cloud-commons/pom.xml index 44e95136..fd136d5b 100644 --- a/spring-cloud-commons/pom.xml +++ b/spring-cloud-commons/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT .. spring-cloud-commons diff --git a/spring-cloud-context-integration-tests/pom.xml b/spring-cloud-context-integration-tests/pom.xml index 07b56be6..6eea481a 100644 --- a/spring-cloud-context-integration-tests/pom.xml +++ b/spring-cloud-context-integration-tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT .. spring-cloud-context-integration-tests diff --git a/spring-cloud-context-webflux-integration-tests/pom.xml b/spring-cloud-context-webflux-integration-tests/pom.xml index 8262f599..00de6588 100644 --- a/spring-cloud-context-webflux-integration-tests/pom.xml +++ b/spring-cloud-context-webflux-integration-tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT .. spring-cloud-context-webflux-integration-tests diff --git a/spring-cloud-context/pom.xml b/spring-cloud-context/pom.xml index 6042bdff..6970f45d 100644 --- a/spring-cloud-context/pom.xml +++ b/spring-cloud-context/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT .. spring-cloud-context diff --git a/spring-cloud-loadbalancer/pom.xml b/spring-cloud-loadbalancer/pom.xml index e5b19aa6..ee1f833f 100644 --- a/spring-cloud-loadbalancer/pom.xml +++ b/spring-cloud-loadbalancer/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT .. spring-cloud-loadbalancer diff --git a/spring-cloud-starter-bootstrap/pom.xml b/spring-cloud-starter-bootstrap/pom.xml index 6bb820f9..ad8ad701 100644 --- a/spring-cloud-starter-bootstrap/pom.xml +++ b/spring-cloud-starter-bootstrap/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT .. jar diff --git a/spring-cloud-starter-loadbalancer/pom.xml b/spring-cloud-starter-loadbalancer/pom.xml index 3e4269b6..a7a5dd16 100644 --- a/spring-cloud-starter-loadbalancer/pom.xml +++ b/spring-cloud-starter-loadbalancer/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT .. 4.0.0 diff --git a/spring-cloud-starter/pom.xml b/spring-cloud-starter/pom.xml index 2e2f2d47..e244fc64 100644 --- a/spring-cloud-starter/pom.xml +++ b/spring-cloud-starter/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT spring-cloud-starter spring-cloud-starter diff --git a/spring-cloud-test-support/pom.xml b/spring-cloud-test-support/pom.xml index daac488c..f6bb1e45 100644 --- a/spring-cloud-test-support/pom.xml +++ b/spring-cloud-test-support/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-commons-parent - 3.1.7-SNAPSHOT + 3.1.8-SNAPSHOT .. spring-cloud-test-support From 8f65504863f205951a6898c4a3e1a2189e619ce4 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Fri, 30 Jun 2023 02:11:21 +0000 Subject: [PATCH 07/12] Bumping versions --- docs/src/main/asciidoc/_configprops.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 93facf98..b58bcd80 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -30,6 +30,7 @@ |spring.cloud.loadbalancer.cache.capacity | `+++256+++` | Initial cache capacity expressed as int. |spring.cloud.loadbalancer.cache.enabled | `+++true+++` | Enables Spring Cloud LoadBalancer caching mechanism. |spring.cloud.loadbalancer.cache.ttl | `+++35s+++` | Time To Live - time counted from writing of the record, after which cache entries are expired, expressed as a {@link Duration}. The property {@link String} has to be in keeping with the appropriate syntax as specified in Spring Boot StringToDurationConverter. @see StringToDurationConverter.java +|spring.cloud.loadbalancer.call-get-with-request-on-delegates | `+++false+++` | If this flag is set to {@code true}, {@code ServiceInstanceListSupplier#get(Request request)} method will be implemented to call {@code delegate.get(request)} in classes assignable from {@code DelegatingServiceInstanceListSupplier} that don't already implement that method, with the exclusion of {@code CachingServiceInstanceListSupplier} and {@code HealthCheckServiceInstanceListSupplier}, which should be placed in the instance supplier hierarchy directly after the supplier performing instance retrieval over the network, before any request-based filtering is done. Note: in 4.1, this behaviour will become the default |spring.cloud.loadbalancer.clients | | |spring.cloud.loadbalancer.configurations | `+++default+++` | Enables a predefined LoadBalancer configuration. |spring.cloud.loadbalancer.enabled | `+++true+++` | Enables Spring Cloud LoadBalancer. From 172452d2ed3bee420359fc4ac8f7ebb3fd6ac898 Mon Sep 17 00:00:00 2001 From: Olga MaciaszekSharma Date: Fri, 30 Jun 2023 11:52:03 +0200 Subject: [PATCH 08/12] Update copyright and fix docs. --- .../main/asciidoc/spring-cloud-commons.adoc | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc index 893341f9..4e5ce418 100644 --- a/docs/src/main/asciidoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -933,11 +933,8 @@ to `false`. WARNING: Although the basic, non-cached, implementation is useful for prototyping and testing, it's much less efficient than the cached versions, so we recommend always using the cached version in production. If the caching is already done by the `DiscoveryClient` implementation, for example `EurekaDiscoveryClient`, the load-balancer caching should be disabled to prevent double caching. -==== - NOTE: When you create your own configuration, if you use `CachingServiceInstanceListSupplier` make sure to place it in the hierarchy directly after the supplier that retrieves the instances over the network, for example, `DiscoveryClientServiceInstanceListSupplier`, before any other filtering suppliers. -==== === Zone-Based Load-Balancing To enable zone-based load-balancing, we provide the `ZonePreferenceServiceInstanceListSupplier`. @@ -1031,12 +1028,8 @@ You can also pass your own `WebClient` or `RestTemplate` instance to be used for WARNING: `HealthCheckServiceInstanceListSupplier` has its own caching mechanism based on Reactor Flux `replay()`. Therefore, if it's being used, you may want to skip wrapping that supplier with `CachingServiceInstanceListSupplier`. -==== - NOTE: When you create your own configuration, `HealthCheckServiceInstanceListSupplier`, make sure to place it in the hierarchy directly after the supplier that retrieves the instances over the network, for example, `DiscoveryClientServiceInstanceListSupplier`, before any other filtering suppliers. -==== - === Same instance preference for LoadBalancer You can set up the LoadBalancer in such a way that it prefers the instance that was previously selected, if that instance is available. @@ -1190,7 +1183,6 @@ and https://github.com/stoyanr/Evictor[Evictor]. You can also use the `@LoadBalancerClient` annotation to pass your own load-balancer client configuration, passing the name of the load-balancer client and the configuration class, as follows: -==== [source,java,indent=0] ---- @Configuration @@ -1205,10 +1197,10 @@ public class MyConfiguration { } ---- -TIP:: In order to make working on your own LoadBalancer configuration easier, we have added a `builder()` method to the `ServiceInstanceListSupplier` class. +TIP: In order to make working on your own LoadBalancer configuration easier, we have added a `builder()` method to the `ServiceInstanceListSupplier` class. + +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. -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. -==== You can use this feature to instantiate different implementations of `ServiceInstanceListSupplier` or `ReactorLoadBalancer`, either written by you, or provided by us as alternatives (for example `ZonePreferenceServiceInstanceListSupplier`) to override the default setup. @@ -1218,7 +1210,6 @@ NOTE: The annotation `value` arguments (`stores` in the example above) specifies You can also pass multiple configurations (for more than one load-balancer client) through the `@LoadBalancerClients` annotation, as the following example shows: -==== [source,java,indent=0] ---- @Configuration @@ -1232,17 +1223,11 @@ public class MyConfiguration { } } ---- -==== NOTE: The classes you pass as `@LoadBalancerClient` or `@LoadBalancerClients` configuration arguments should either not be annotated with `@Configuration` or be outside component scan scope. -==== - -==== - NOTE: When you create your own configuration, if you use `CachingServiceInstanceListSupplier` or `HealthCheckServiceInstanceListSupplier`, makes sure to use one of them, not both, and make sure to place it in the hierarchy directly after the supplier that retrieves the instances over the network, for example, `DiscoveryClientServiceInstanceListSupplier`, before any other filtering suppliers. -==== [[loadbalancer-lifecycle]] === Spring Cloud LoadBalancer Lifecycle From 8531a7d40b311496ada15edc0daa233829b255e9 Mon Sep 17 00:00:00 2001 From: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com> Date: Fri, 30 Jun 2023 09:55:52 -0400 Subject: [PATCH 09/12] Update to Spring Security RSA 1.0.12 --- spring-cloud-commons-dependencies/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-commons-dependencies/pom.xml b/spring-cloud-commons-dependencies/pom.xml index b86e33f2..83de3e98 100644 --- a/spring-cloud-commons-dependencies/pom.xml +++ b/spring-cloud-commons-dependencies/pom.xml @@ -15,7 +15,7 @@ spring-cloud-commons-dependencies Spring Cloud Commons Dependencies - 1.0.11.RELEASE + 1.0.12.RELEASE From 78d87d6547aea51d3e12bd6fb15556664fa1fae5 Mon Sep 17 00:00:00 2001 From: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com> Date: Fri, 30 Jun 2023 10:19:22 -0400 Subject: [PATCH 10/12] Build 4.0.x branch in github actions --- .github/workflows/maven.yaml | 42 ------------------------------------ .github/workflows/maven.yml | 4 ++-- 2 files changed, 2 insertions(+), 44 deletions(-) delete mode 100644 .github/workflows/maven.yaml diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml deleted file mode 100644 index 748dfdcc..00000000 --- a/.github/workflows/maven.yaml +++ /dev/null @@ -1,42 +0,0 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - -name: Build - -on: - push: - branches: [ main, 3.1.x ] - pull_request: - branches: [ main, 3.1.x ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: '17' - - name: Cache local Maven repository - uses: actions/cache@v2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - name: Build with Maven - run: ./mvnw -s .settings.xml clean org.jacoco:jacoco-maven-plugin:prepare-agent install -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn - - name: Publish Test Report - uses: mikepenz/action-junit-report@v2 - if: always() # always run even if the previous step fails - with: - report_paths: '**/surefire-reports/TEST-*.xml' - - name: Archive code coverage results - uses: actions/upload-artifact@v2 - with: - name: surefire-reports - path: '**/surefire-reports/*' diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 748dfdcc..9b781b39 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -5,9 +5,9 @@ name: Build on: push: - branches: [ main, 3.1.x ] + branches: [ main, 4.0.x, 3.1.x ] pull_request: - branches: [ main, 3.1.x ] + branches: [ main, 4.0.x, 3.1.x ] jobs: build: From d796c28527a1a94738c5a743dc530e47bfbe8d18 Mon Sep 17 00:00:00 2001 From: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com> Date: Fri, 30 Jun 2023 10:29:13 -0400 Subject: [PATCH 11/12] Revert to spring-security-rsa 1.0.11 --- spring-cloud-commons-dependencies/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-commons-dependencies/pom.xml b/spring-cloud-commons-dependencies/pom.xml index 83de3e98..b86e33f2 100644 --- a/spring-cloud-commons-dependencies/pom.xml +++ b/spring-cloud-commons-dependencies/pom.xml @@ -15,7 +15,7 @@ spring-cloud-commons-dependencies Spring Cloud Commons Dependencies - 1.0.12.RELEASE + 1.0.11.RELEASE From fb879e7cf1d32ae26e53b42a003e0b543548d936 Mon Sep 17 00:00:00 2001 From: Olga MaciaszekSharma Date: Fri, 30 Jun 2023 17:32:58 +0200 Subject: [PATCH 12/12] Adjust docs. --- docs/src/main/asciidoc/spring-cloud-commons.adoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc index 03813c63..7f213d75 100644 --- a/docs/src/main/asciidoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -949,8 +949,6 @@ WARNING: Although the basic, non-cached, implementation is useful for prototypin NOTE: When you create your own configuration, if you use `CachingServiceInstanceListSupplier` make sure to place it in the hierarchy directly after the supplier that retrieves the instances over the network, for example, `DiscoveryClientServiceInstanceListSupplier`, before any other filtering suppliers. -==== - === Weighted Load-Balancing To enable weighted load-balancing, we provide the `WeightedServiceInstanceListSupplier`. We use `WeightFunction` to calculate the weight of each instance.