zoukankan      html  css  js  c++  java
  • SpringCloud负载均衡之Ribbon源码剖析

    前面我们已经看了注册中心Eureka的源码,接下来我们看一下springcloud的负载均衡器Ribbon的源码

    我们先看一下org.springframework.cloud.client.loadbalancer.LoadBalanced注解里都有啥

     这里啥也没有但是我们可以从注释中知道,restTemplate被LoadBalanced标记了之后会使用LoadBalancerClient进行处理

    这里没发现线索,咱们就去他的老家拜访拜访

     接下来我们看看org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration里都做了啥

     我们重点看看被标红的两个地方1、@AutoConfigureBefore中的LoadBalancerAutoConfiguration.class ;2、当前配置类org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration。AutoConfigureBefore的意思就是说这个类时当前类装配之后这个注解中的类才会被装配,接下来我们分别分析一下这两个类

    进入org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration

     我们可以看到要装配这个bean有两个条件1、得先有ResTemplate;2、得现有LoadBancerClient。由于我们使用springcloud发送请求是用ResTemplate进行请求发送,所以ResTemplate是我们人为注入进去的。而LoadBancerClient是什么时候注入的呢?

    此时我们回想起AutoConfigureBefore这个注解的作用,哦,会不会在org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration注入进去的呢?我们去看看

     果不其然,就是在这里注入的回到org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration中继续往下看

     这里注入了一个list,被LoadBalanced标记的RestTemplate都会存放到这个list里而这个list是什么时候被使用的呢?

     可以看到是在org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration#loadBalancedRestTemplateInitializerDeprecated中,这里是在使用定制器org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer定制restTemplate,而定制器是在什么时候注入的呢?我们继续往下找发现在org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.LoadBalancerInterceptorConfig#restTemplateCustomizer中

     

     这里是直接把一个拦截器org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor添加到定制器中,而这个拦截器什么时候注入的呢?我们向上看一点就能找到

     而这个拦截器是干啥的呢?我们点进去看看此时来到LoadBalancerInterceptor类中

     我们重点关注一下这个intercept方法中,这里面使用负载均衡客户端执行,我们点进去看看

     我们进入到org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient#execute方法中看看这里又做了啥

     可以看到这里主要就做了三件事1、获取负载均衡器;2、获取服务端信息;3、具体执行。接下来我们就具体分析一下里面的情况

    1、获取负载均衡器,我们进入org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient#getLoadBalancer方法中

     继续跟进org.springframework.cloud.netflix.ribbon.SpringClientFactory#getLoadBalancer方法

     再跟进org.springframework.cloud.netflix.ribbon.SpringClientFactory#getLoadBalancer

     再继续跟进org.springframework.cloud.netflix.ribbon.SpringClientFactory#getInstance方法

     继续跟进org.springframework.cloud.context.named.NamedContextFactory#getInstance方法

     发现这里就是从容器中获取到一个bean,直接返回,而SpringClientFactory是什么时候注入进去的呢?大家如果还有印象,我们在注入 LoadBalancerClient的时候好像有点印象我们一起来看看

     我们进入他的构造方法里看看

     嗯,在点进这个org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration类里看看去

     不点不知道,一点吓一跳,原来ribbon的基本组件都在这里进行装配了。

     

     soga,好了我们知道是如何获取负载均衡器了,接下来我们看看如何获取服务信息的

    2、获取服务信息

    进入org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient#getServer方法中

     继续进入方法

    额,这里进哪个呢?咱们回想一下之前在获取server的时候是不是有一个类在组装ribbon的基本组件啊,这个负载均衡器应该就在那里注入的?我们回去看看

    进入org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration找一下

     果不其然,在这个类里发现了他,这里默认使用的是区域隔离负载均衡器

    那咱们进入com.netflix.loadbalancer.ZoneAwareLoadBalancer#chooseServer方法中

    继续进入com.netflix.loadbalancer.BaseLoadBalancer#chooseServer方法中

     继续进入com.netflix.loadbalancer.IRule#choose方法中

     这又如何抉择呢?还是回到之前组装基本组件中找找有没有相关信息

     好家伙,这也没找到啊。别着急,咱们点进这个rule里看看

     哦,原来如此。因此我们来到com.netflix.loadbalancer.PredicateBasedRule#choose方法

     继续进入com.netflix.loadbalancer.AbstractServerPredicate#chooseRoundRobinAfterFiltering方法

    嗯,看起来像是在这里,进去看看

     终于到头了这里其实也就是一个轮询获取服务信息。好了,我们接下来再看看下一步是做什么?

    我们回到之前的org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient#execute方法中

     进入这个方法中看看

     进入org.springframework.cloud.client.loadbalancer.LoadBalancerRequest#apply方法中

     进入org.springframework.http.client.InterceptingAsyncClientHttpRequest.AsyncRequestExecution#executeAsync方法

     继续进入org.springframework.http.client.AsyncClientHttpRequest#executeAsync方法

     此时我们已经进入了org.springframework.http.client.AbstractAsyncClientHttpRequest类中,这个类是不是很熟悉啊,好像在哪见过呢?没错,ResTemplate就是通过他来发请求的,我们也可以顺便看看ResTemplate

     

     

     

     好了,到这里咱们的Ribbon的源码基本就看完了,所以这个过程中ribbon都做了啥呢?

    1、获取客户端服务列表

    2、从客户端服务列表中选取一个服务

    3、使用ResTemplate发送请求

    那这些事情都ribbon是怎么做到的呢?其实他就是在装配bean的时候给加上@LoadBalanced的注解的ResTemplate添加上了拦截器,最终使用拦截器去做的这些事情

  • 相关阅读:
    常见业务指标
    1006 换个格式输出整数 (Python)
    1004 成绩排名 (Python)
    1003 我要通过! (Python)
    1008 数组元素循环右移问题 (Python)
    如何使用SSH秘钥链接Github
    在windows下如何正确安装curses模块
    面向数据结构C基础知识点(个人向)
    用Python实现链式调用
    python重点串讲
  • 原文地址:https://www.cnblogs.com/qsky/p/13845099.html
Copyright © 2011-2022 走看看