Gh 576 use reactive load balancer (#584)

* Add `ReactorLoadBalancerClient` interface and its default implementation.

* Add initial `ReactorLoadBalancerExchangeFilterFunction` implementation.
Add `ReactorLoadBalancerClientAutoConfiguration`.
Refactor `ReactorLoadBalancerClient` interface and default implementation.

* Implement configuration changes to make default `ReactorLoadBalancer` and
`ReactorLoadBalancerClient` work out of the box with `@LoadBalanced
WebClient.Builder`.

* Add more tests for ReactorLoadBalancerExchangeFilterFunction and
DefaultReactorLoadBalancer.

* Fix configuration. Add tests. Add documentation.

* Add information on caching to the documentation.

* Add fixes after code review.

* Small refactoring after code review.

* Switch from handle(response, sink) to map(response).

* Remove redundant cast.

* Add link to caching in Springboot reference to the docs.

* Add more information on working with spring-cloud-loadbalancer vs. spring-cloud-starter-netflix-ribbon to the docs.

* Fix after code review.
This commit is contained in:
Olga Maciaszek-Sharma
2019-08-12 11:40:26 +02:00
committed by GitHub
parent 2e714b6757
commit 3f17c0d902
19 changed files with 1200 additions and 31 deletions

View File

@@ -17,25 +17,34 @@
package org.springframework.cloud.loadbalancer.annotation;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceSupplier;
import org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
/**
* @author Spencer Gibb
* @author Olga Maciaszek-Sharma
*/
@Configuration
@EnableConfigurationProperties
@ConditionalOnDiscoveryEnabled
public class LoadBalancerClientConfiguration {
@Bean
@ConditionalOnBean(DiscoveryClient.class)
@ConditionalOnMissingBean
public ServiceInstanceSupplier discoveryClientServiceInstanceSupplier(
DiscoveryClient discoveryClient, Environment env,
@@ -50,4 +59,14 @@ public class LoadBalancerClientConfiguration {
return delegate;
}
@Bean
@ConditionalOnMissingBean
public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(
Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RoundRobinLoadBalancer(name, loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceSupplier.class));
}
}

View File

@@ -20,6 +20,9 @@ import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancerAutoConfiguration;
import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
@@ -28,9 +31,12 @@ import org.springframework.context.annotation.Configuration;
/**
* @author Spencer Gibb
* @author Olga Maciaszek-Sharma
*/
@Configuration
@LoadBalancerClients
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,
ReactiveLoadBalancerAutoConfiguration.class })
// @EnableCaching //TODO: how to enforce, or check conditions?
// @AutoConfigureBefore(CacheAutoConfiguration.class)
public class LoadBalancerAutoConfiguration {

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.loadbalancer.core;
import org.springframework.cloud.client.ServiceInstance;
/**
* A marker interface for {@link ReactorLoadBalancer} that allows selecting
* {@link ServiceInstance} objects.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
*/
public interface ReactorServiceInstanceLoadBalancer
extends ReactorLoadBalancer<ServiceInstance> {
}

View File

@@ -33,7 +33,7 @@ import org.springframework.cloud.client.loadbalancer.reactive.Response;
/**
* @author Spencer Gibb
*/
public class RoundRobinLoadBalancer implements ReactorLoadBalancer<ServiceInstance> {
public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private static final Log log = LogFactory.getLog(RoundRobinLoadBalancer.class);

View File

@@ -16,9 +16,12 @@
package org.springframework.cloud.loadbalancer.support;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
import org.springframework.cloud.context.named.NamedContextFactory;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfiguration;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.core.env.Environment;
/**
@@ -28,9 +31,11 @@ import org.springframework.core.env.Environment;
*
* @author Spencer Gibb
* @author Dave Syer
* @author Olga Maciaszek-Sharma
*/
public class LoadBalancerClientFactory
extends NamedContextFactory<LoadBalancerClientSpecification> {
extends NamedContextFactory<LoadBalancerClientSpecification>
implements ReactiveLoadBalancer.Factory<ServiceInstance> {
/**
* Property source name for load balancer.
@@ -50,4 +55,9 @@ public class LoadBalancerClientFactory
return environment.getProperty(PROPERTY_NAME);
}
@Override
public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId) {
return getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);
}
}