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添加上了拦截器,最终使用拦截器去做的这些事情

原文地址:https://www.cnblogs.com/qsky/p/13845099.html