Add hints to API via the Request interface. Fixes gh-647. (#669)
* Add hints to API via the Request interface. Fixes gh-647. * Switch to generic context.
This commit is contained in:
committed by
Spencer Gibb
parent
232c7f71d2
commit
ec784b757e
@@ -17,8 +17,30 @@
|
||||
package org.springframework.cloud.client.loadbalancer.reactive;
|
||||
|
||||
/**
|
||||
* A default implementation of {@link Request}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class DefaultRequest implements Request {
|
||||
public class DefaultRequest<T> implements Request<T> {
|
||||
|
||||
private T context;
|
||||
|
||||
public DefaultRequest() {
|
||||
new DefaultRequestContext();
|
||||
}
|
||||
|
||||
public DefaultRequest(T context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setContext(T context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.client.loadbalancer.reactive;
|
||||
|
||||
/**
|
||||
* Contains information relevant to the request.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class DefaultRequestContext {
|
||||
|
||||
/**
|
||||
* A {@link String} value of hint that can be used to choose the correct service
|
||||
* instance.
|
||||
*/
|
||||
private String hint = "default";
|
||||
|
||||
public DefaultRequestContext() {
|
||||
}
|
||||
|
||||
public DefaultRequestContext(String hint) {
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
public String getHint() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
public void setHint(String hint) {
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,13 +30,14 @@ public interface ReactiveLoadBalancer<T> {
|
||||
/**
|
||||
* Default implementation of a request.
|
||||
*/
|
||||
Request REQUEST = new DefaultRequest();
|
||||
Request<DefaultRequestContext> REQUEST = new DefaultRequest();
|
||||
|
||||
/**
|
||||
* Choose the next server based on the load balancing algorithm.
|
||||
* @param request - incoming request
|
||||
* @return publisher for the response
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
Publisher<Response<T>> choose(Request request);
|
||||
|
||||
default Publisher<Response<T>> choose() { // conflicting name
|
||||
|
||||
@@ -20,8 +20,14 @@ package org.springframework.cloud.client.loadbalancer.reactive;
|
||||
* Marker interface for a request.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public interface Request {
|
||||
public interface Request<C> {
|
||||
|
||||
// Avoid breaking backward compatibility
|
||||
default C getContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: define contents
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ public interface ReactorLoadBalancer<T> extends ReactiveLoadBalancer<T> {
|
||||
* @param request - an input request
|
||||
* @return - mono of response
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
Mono<Response<T>> choose(Request request);
|
||||
|
||||
default Mono<Response<T>> choose() {
|
||||
|
||||
@@ -104,6 +104,7 @@ public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalance
|
||||
this.position = new AtomicInteger(seedPosition);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
// see original
|
||||
// https://github.com/Netflix/ocelli/blob/master/ocelli-core/
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
@@ -33,7 +34,11 @@ import org.springframework.cloud.client.DefaultServiceInstance;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.CompletionContext;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.CompletionContext.Status;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.DefaultRequest;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.DefaultRequestContext;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.DefaultResponse;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.Request;
|
||||
import org.springframework.cloud.client.loadbalancer.reactive.Response;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||
@@ -45,6 +50,7 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
/**
|
||||
@@ -125,6 +131,11 @@ public class LoadBalancerTests {
|
||||
assertLoadBalancer(loadBalancer, Arrays.asList("1host", "2host-secure"));
|
||||
}
|
||||
|
||||
private static DefaultServiceInstance instance(String serviceId, String host,
|
||||
boolean secure) {
|
||||
return new DefaultServiceInstance(serviceId, serviceId, host, 80, secure);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticConfigurationWorksWithServiceInstanceListSupplier() {
|
||||
String serviceId = "test1";
|
||||
@@ -136,9 +147,44 @@ public class LoadBalancerTests {
|
||||
assertLoadBalancer(loadBalancer, Arrays.asList("1host", "2host-secure"));
|
||||
}
|
||||
|
||||
private DefaultServiceInstance instance(String serviceId, String host,
|
||||
boolean secure) {
|
||||
return new DefaultServiceInstance(serviceId, serviceId, host, 80, secure);
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Test
|
||||
public void canPassHintViaRequest() {
|
||||
String serviceId = "test1";
|
||||
RoundRobinLoadBalancer loadBalancer = new TestHintLoadBalancer(
|
||||
ServiceInstanceListSuppliers.toProvider(serviceId,
|
||||
instance(serviceId, "1host", false),
|
||||
instance(serviceId, "2host-secure", true)),
|
||||
serviceId);
|
||||
Request<DefaultRequestContext> request = new DefaultRequest<>(
|
||||
new DefaultRequestContext("test2"));
|
||||
|
||||
ServiceInstance serviceInstance = loadBalancer.choose(request).block()
|
||||
.getServer();
|
||||
|
||||
assertThat(serviceInstance.getServiceId()).isEqualTo("test2");
|
||||
}
|
||||
|
||||
private static class TestHintLoadBalancer extends RoundRobinLoadBalancer {
|
||||
|
||||
TestHintLoadBalancer(
|
||||
ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
|
||||
String serviceId) {
|
||||
super(serviceInstanceListSupplierProvider, serviceId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public Mono<Response<ServiceInstance>> choose(Request request) {
|
||||
if (request.getContext() instanceof DefaultRequestContext) {
|
||||
DefaultRequestContext requestContext = (DefaultRequestContext) request
|
||||
.getContext();
|
||||
return Mono.just(new DefaultResponse(
|
||||
instance(requestContext.getHint(), "host", false)));
|
||||
}
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
|
||||
Reference in New Issue
Block a user