## Ribbon学习(二)——Ribbon核心源码分析
[TOC]
## Ribbon核心原理图
**Ribbon原理图介绍**:

其实Ribbon主要的原理是给RestTemplate加了一个拦截器,当我们访问服务端的时候,Ribbon先获取到服务端的所有服务列表,再根据一定的负载均衡策略从实例列表中获取到具体的实例Server,最终使用RestTemplate进行请求访问
**细节结构图**:

Ribbon主要是围绕LoadBalancer进行获取数据的列表,服务的更新,选取服务等,主要有以下四大组件:
- IRule:是在选择实例的时候的负载均衡策略对象
- IPing:是⽤来向服务发起⼼跳检测的,通过⼼跳检测来判断该服务是否可⽤
- ServerListFilter:根据⼀些规则过滤传⼊的服务实例列表
- ServerListUpdater:定义了⼀系列的对服务列表的更新操作
## Ribbon的源码分析
### @LoadBalanced源码剖析
- 因为我们在使用Ribbon的时候,其实就是在RestTemplate上增加了一个@LoadBalanced注解,加上注解之后,RestTemplate可以自动的进行负载均衡,现在我们也从@LoadBalanced注解中开始追溯这里可以看到,使用@LoadBalanced可以把普通的RestTemplate请求转换为LoadBalancerClient对象,这里后面再进行查看。
- 现在来查看Ribbon依赖中的自动注入配置这里还是使用了SpringBoot的自动装配机制,装配了`org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration`配置类
- **RestTemplate的初始化**:
进入RibbonAutoConfiguration配置类
先查看
2、进入`LoadBalancerAutoConfiguration`类,

只有在存在RestTemplate类和LoadBalancerClient类的情况下,才会装配本类,并且还看到声明了一个restTemplates的集合,这里注入了所有标注了@Loadbalanced注解的RestTemplate类
3、遍历所有的RestTemplate类,进行拦截

4、为RestTemplate增加LoadBalancerInterceptor拦截器

到了这里和前面的分析,可以得知Ribbon就是通过拦截器来实现负载均衡的,那我们这里就要去看具体的拦截器是如何实现的了,
5、LoadBalancerInterceptor拦截器的具体实现

- **LoadBalancerClient的注入**:
回到前面,LoadBalancerClient是如何注入的,进入初始的`org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration`类,

负载均衡的具体处理逻辑,统一交给了`RibbonLoadBalancerClient`来处理了,这里有个最重要的方法,`org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient#execute()`

- 这里带来一个新的问题,ILoadBalancer是如何注入的,进入方法查看


那我们就要来看SpringClientFactory类是如何注入的了
- 回到`RibbonAutoConfiguration`类

这里将RibbonClientSpecification配置信息注入到了SpringClientFactory中,也完成了SpringClientFactory的注入
- **SpringClientFactory注入过程**:
进入SpringClientFactory

这里面的RibbonClientConfiguration中装配了大脑和枝干,这里可以看到默认的IRule,IPing

默认的ILoadBalancer,ServerListFilter

默认的ServerListUpdater

- 这样上面我们就完成了LoadBalancerClient的注入,现在回到`LoadBalancerInterceptor`拦截器,进行调试查看

进入execute方法,获取到默认的ZoneAwareLoadBalancer的大脑

进入`com.netflix.loadbalancer.ZoneAwareLoadBalancer#chooseServer`方法,


获取所有的服务列表:



这里使用轮询的方式,获取到本次应该获取到的服务请求实例


进入AbstractClientHttpRequest#execute`方法

最终这里真正的创建了请求并获取返回值

**注入ServerList与更新ServerList**
- 进入`RibbonClientConfiguration`类,查看到ServerList的初始化,这里看到默认值初始化了一个空的List

- 这里应该是只做了一个普通的初始化,具体的ServerList在其他地方对其初始化,查看到ILoadBalancer中使用了serverList,serverListUpdater,猜测这里是会对其进行数据获取

进入ZoneAwareLoadBalancer的构造方法

再次进入到父级的构造方法,`com.netflix.loadbalancer.DynamicServerListLoadBalancer#DynamicServerListLoadBalancer()`

进入关键方法:restOfInit()方法

进入`enableAndInitLearnNewServersFeature()`方法

查看updateAction

这里启动了一个定时任务,定时调用updateAction中的doUpdate()方法,

最终后台任务会定时去Eureka客户端获取到所有的服务列表

这样就完成了整体的请求、服务更新的代码分析
Ribbon学习(二)——Ribbon核心源码分析