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:
committed by
GitHub
parent
2e714b6757
commit
3f17c0d902
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user