Browse Source

Create a LoadBalancerClient abstraction and a Ribbon implementation

pull/6/head
Spencer Gibb 10 years ago
parent
commit
23b8c96b11
  1. 11
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/client/ServiceInstance.java
  2. 15
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerClient.java
  3. 23
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java
  4. 22
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonInterceptor.java
  5. 40
      spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java

11
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/client/ServiceInstance.java

@ -0,0 +1,11 @@
package org.springframework.cloud.client;
/**
* @author Spencer Gibb
* TODO: name? Server? HostAndPort? Instance?
*/
public interface ServiceInstance {
public String getHost();
public int getPort();
}

15
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerClient.java

@ -0,0 +1,15 @@
package org.springframework.cloud.client.loadbalancer;
import org.springframework.cloud.client.ServiceInstance;
/**
* @author Spencer Gibb
*/
public interface LoadBalancerClient {
/**
* Choose a {@see ServiceInstance} from the LoadBalancer for the specified service
* @param serviceId The serviceId to use to look up the LoadBalancer
* @return
*/
public ServiceInstance choose(String serviceId);
}

23
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java

@ -3,6 +3,7 @@ package org.springframework.cloud.netflix.ribbon;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration; import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EurekaRibbonInitializer; import org.springframework.cloud.netflix.eureka.EurekaRibbonInitializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -10,7 +11,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -27,19 +27,22 @@ public class RibbonAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean(RestTemplate.class) @ConditionalOnMissingBean(RestTemplate.class)
public RestTemplate restTemplate() { public RestTemplate restTemplate(RibbonInterceptor ribbonInterceptor) {
return new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
List<ClientHttpRequestInterceptor> list = new ArrayList<>();
list.add(ribbonInterceptor);
restTemplate.setInterceptors(list);
return restTemplate;
} }
@Bean @Bean
public RibbonInterceptor ribbonInterceptor() { @ConditionalOnMissingBean(LoadBalancerClient.class)
return new RibbonInterceptor(); public LoadBalancerClient loadBalancerClient() {
return new RibbonLoadBalancerClient();
} }
@PostConstruct @Bean
public void init() { public RibbonInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient) {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(); return new RibbonInterceptor(loadBalancerClient);
list.add(ribbonInterceptor());
restTemplate().setInterceptors(list);
} }
} }

22
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonInterceptor.java

@ -1,8 +1,7 @@
package org.springframework.cloud.netflix.ribbon; package org.springframework.cloud.netflix.ribbon;
import com.netflix.client.ClientFactory; import org.springframework.cloud.client.ServiceInstance;
import com.netflix.loadbalancer.ILoadBalancer; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import com.netflix.loadbalancer.Server;
import org.springframework.http.HttpRequest; import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpRequestInterceptor;
@ -17,6 +16,13 @@ import java.net.URI;
* @author Spencer Gibb * @author Spencer Gibb
*/ */
public class RibbonInterceptor implements ClientHttpRequestInterceptor { public class RibbonInterceptor implements ClientHttpRequestInterceptor {
private LoadBalancerClient loadBalancer;
public RibbonInterceptor(LoadBalancerClient loadBalancer) {
this.loadBalancer = loadBalancer;
}
@Override @Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
HttpRequestWrapper wrapper = new HttpRequestWrapper(request) { HttpRequestWrapper wrapper = new HttpRequestWrapper(request) {
@ -24,14 +30,10 @@ public class RibbonInterceptor implements ClientHttpRequestInterceptor {
public URI getURI() { public URI getURI() {
URI originalUri = super.getURI(); URI originalUri = super.getURI();
String serviceName = originalUri.getHost(); String serviceName = originalUri.getHost();
ILoadBalancer loadBalancer = ClientFactory.getNamedLoadBalancer(serviceName); ServiceInstance instance = loadBalancer.choose(serviceName);
Server server = loadBalancer.chooseServer(null);
if (server == null) {
throw new IllegalStateException("Unable to locate ILoadBalancer for service: "+ serviceName);
}
URI uri = UriComponentsBuilder.fromUri(originalUri) URI uri = UriComponentsBuilder.fromUri(originalUri)
.host(server.getHost()) .host(instance.getHost())
.port(server.getPort()) .port(instance.getPort())
.build() .build()
.toUri(); .toUri();
return uri; return uri;

40
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java

@ -0,0 +1,40 @@
package org.springframework.cloud.netflix.ribbon;
import com.netflix.client.ClientFactory;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
/**
* @author Spencer Gibb
*/
public class RibbonLoadBalancerClient implements LoadBalancerClient {
@Override
public ServiceInstance choose(String serviceId) {
ILoadBalancer loadBalancer = ClientFactory.getNamedLoadBalancer(serviceId);
Server server = loadBalancer.chooseServer(null);
if (server == null) {
throw new IllegalStateException("Unable to locate ILoadBalancer for service: "+ serviceId);
}
return new RibbonServer(server);
}
private class RibbonServer implements ServiceInstance {
private Server server;
private RibbonServer(Server server) {
this.server = server;
}
@Override
public String getHost() {
return server.getHost();
}
@Override
public int getPort() {
return server.getPort();
}
}
}
Loading…
Cancel
Save