聊聊Ribbon源码解读

举报
周杰伦本人 发表于 2022/09/29 13:34:50 2022/09/29
【摘要】 聊聊Ribbon源码解读要说当今最流行的组件当然是SpringCloud,要说框架中最流行的负载均衡组件,非Ribbon莫属了。随着用户量的逐渐增多,一台机器不足以支持用户的请求,这就需要多台机器来共同承当这个请求量,这就是需要负载均衡技术了 @LoadBalanced注解当我们使用Ribbon的时候,spring中注入RestTemplate,并在上边添加 @LoadBalanced,这...

聊聊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实例中添加拦截器LoadBalancerInterceptor,然后RestTemplate定制器RestTemplateCustomizer会向restTemplates集合中遍历每个restTemplate来添加拦截器

拦截器

那我们需要看一下LoadBalancerInterceptor拦截器了,众所周知,拦截器最重要的就是它的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拦截器的,以及拦截器的拦截方法中调用RibbonLoadBalancerClient的execute(),接着分析了execute()方法中先获取拦截器,再选择服务,然后执行execute()方法

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。