聊聊Ribbon源码解读

要说当今最流行的组件当然是SpringCloud,要说框架中最流行的负载均衡组件,非Ribbon莫属了

@LoadBalanced注解

当我们使用Ribbon的时候,spring中注入RestTemplate,并在上边添加 @LoadBalanced,这样使用RestTemplate发送请求的时候就实现了负载均衡

  @Bean
  @LoadBalanced
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

为什么会这样呢?今天我们分析一下它是什么工作的

配置文件

我们看一下Ribbon包下的spring.factories文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration

配置类

这里显然自动装配了RibbonAutoConfiguration类,这就是入口了,我们深入这个类看一下,类上有个注解

@AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class})

表示RibbonAutoConfiguration加载后加载LoadBalancerAutoConfiguration和AsyncLoadBalancerAutoConfiguration

我们先看一下LoadBalancerAutoConfiguration类,LoadBalancerAutoConfiguration注入了RestTemplateCustomizer对象,并向RestTemplateCustomizer实例中添加lanjie器LoadBalancerInterceptor,然后RestTemplate定制器RestTemplateCustomizer会向restTemplates集合中遍历每个restTemplate来添加lanjie器

lanjie器

那我们需要看一下LoadBalancerInterceptorlanjie器了,众所周知,lanjie器最重要的就是它的intercept()方法

  @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, requestFactory.createRequest(request, body, execution));
  }

request.getURI()会获取到相应的url,originalUri.getHost()会拿到服务名,然后调用LoadBalancerClient的execute(),那么具体是哪个LoadBalancerClient实例呢,通过RibbonAutoConfiguration的bean定义我们知道:

  @Bean
  @ConditionalOnMissingBean(LoadBalancerClient.class)
  public LoadBalancerClient loadBalancerClient() {
    return new RibbonLoadBalancerClient(springClientFactory());
  }

是RibbonLoadBalancerClient,我们看一它的execute()方法

RibbonLoadBalancerClient

RibbonLoadBalancerClient的execute()方法

  @Override
  public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
    ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
    Server server = getServer(loadBalancer);
    if (server == null) {
      throw new IllegalStateException("No instances available for " + serviceId);
    }
    RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
        serviceId), serverIntrospector(serviceId).getMetadata(server));

    return execute(serviceId, ribbonServer, request);
  }
  1. 获取负载均衡器
  2. 使用负载均衡器来选择最终要用的Server服务
  3. 把Server对象封装成RibbonServer
  4. 调用execute()来执行

接下来我们将重点分析下负载均衡器是如何定义的,负载均衡器是怎么选择服务器和execute()方法的逻辑是怎么样的

总结

这篇文章是Ribbon源码解读的第一篇,我们从springboot的自动装配的RibbonAutoConfiguration作为入口,分析了Ribbon是如果给RestTemplate添加LoadBalancerInterceptor lanjie器的,以及lanjie器的lanjie方法中调用RibbonLoadBalancerClient的execute(),接着分析了execute()方法中先获取lanjie器,再选择服务,然后执行execute()方法