美文网首页
SpringCloud 负载均衡与服务调用-探索

SpringCloud 负载均衡与服务调用-探索

作者: quanCN | 来源:发表于2021-04-06 19:38 被阅读0次

前言

在Spring Cloud Commons中提供了大量的与服务治理相关的抽象接口,其中包括DiscoveryClient用于获取注册中心上的服务对应的所有实例。在使用过程中会出现一个问题,在注册中心返回的实例列表中,应该选择哪个实例?服务注册和发现spring文档

LoadBalancerClient

SpringCloud定义了客户端负载均衡接口LoadBalancerClient,客户端负载均衡表示这个操作是在客户端进行的,客户端获取了所有的实例列表,并且根据算法选择其中一个实例。
有了负载均衡特性之后,在开发过程中无须通过DiscoveryClient获取ServiceInstance列表,而是直接进行服务调用,因为SpringCloud在底层屏蔽了负载均衡的逻辑。
如下代码介绍了LoadBalancerClient接口的一个简单用法,LoadBalancerClient相当于负载均衡组件:

List<ServiceInstance> serviceInstances = discoveryClient.getInstances("ORDER-SERVER");
LoadBalancerClient client = new LoadBalancerClient(serviceInstances);
ServiceInstance serviceInstance = client.choose("ORDER-SERVER");
String result = new RestTemplate().getForObject(
        "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/hello",
        String.class
);

LoadBalancerClient(客户端负载均衡器)接口的源码如下

public interface LoadBalancerClient extends ServiceInstanceChooser {
    <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

    <T> T execute(String serviceId, ServiceInstance serviceInstance,
            LoadBalancerRequest<T> request) throws IOException;

    URI reconstructURI(ServiceInstance instance, URI original);
}

LoadBalancerClient接口继承ServiceInstanceChooser(服务实例选择器),源码如下

public interface ServiceInstanceChooser {
    ServiceInstance choose(String serviceId);
}
  • ServiceInstance choose(String serviceId)
    根据传入的服务名serviceId得到一个对应服务的实例。

LoadBalancerClient实现

LoadBalancerClient有多种实现:

  • RibbonLoadBalancerClient
    基于Netflix Ribbon的LoadBalancerClient实现
  • BlockingLoadBalancerClient
    基于Spring Cloud LoadBalancer的LoadBalancerClient实现

SpringCloudLoadBalancer是新一代客户端负载均衡实现,如使用需要引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

@LoadBalanced

使用Spring Cloud可以直接基于服务名进行服务调用。这是因为Spring Cloud扩展了RestTemplate,只需要在定义RestTemplate Bean时加上@LoadBalanced注解,就可以基于服务名进行调用

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}
restTemplate.getForObject("http://ORDER-SERVER/hello", String.class);

Spring Cloud Common提供了LoadBalancerAutoConfiguration这个自动配置类,该类配置了拦截器,所有被@LoadBalanced注解修饰的RestTemplate都会被添加一个拦截器LoadBalancerInterceptor

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {

    private LoadBalancerClient loadBalancer;

    private LoadBalancerRequestFactory requestFactory;

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer,
            LoadBalancerRequestFactory requestFactory) {
        this.loadBalancer = loadBalancer;
        this.requestFactory = requestFactory;
    }

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
        // for backwards compatibility
        this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
    }

    @Override
    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
            final ClientHttpRequestExecution execution) throws IOException {
        final URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        Assert.state(serviceName != null,
                "Request URI does not contain a valid hostname: " + originalUri);
        return this.loadBalancer.execute(serviceName,
                this.requestFactory.createRequest(request, body, execution));
    }

}

LoadBalancerInterceptor构造器需要LoadBalancerClientLoadBalancerRequestFactory,前者根据负载均衡请求和服务名做真正的服务调用,后者构造负载均衡请求

相关文章

网友评论

      本文标题:SpringCloud 负载均衡与服务调用-探索

      本文链接:https://www.haomeiwen.com/subject/mddekltx.html