Ribbon源码

ribbon是一种客户端负载均衡的工具

三大核心组件  ——>  

ILoadBalancer 负载均衡器    IRule  负载算法      IPing  

先来说下大致的底层调用流程吧

假设现在eureka上有一个订单微服务,该服务有两个实例,现在用户服务要去调用订单服务,一般就会通过restTemplate.getForObject(url就是服务名+接口访问路径 )去通用,最终ribbon会获取到eureka-client端里面的订单服务信息并且根据某种负载均衡算法将其服务名称替换为某一个实例ip

开始分析

 首先来到ribbon的入口,@LoadBalanced

了解过springboot的都知道,它会在容器启动的时候把依赖包里面的一些XXXAutoConfiguration配置类加到容器当中,根据猜测定位到LoadBalancerAutoConfiguration配置类

在@LoadBalanced同级包下发现了LoadBalancerAutoConfiguration

 在该配置类下初始化了一个LoadBalancerInterceptor  bean 负载均衡拦截器

该配置类初始化了RestTemplateCustomizer restTemplate定制器的bean, 该bean定制了RestTemplate,  将 LoadBalancerInterceptor封装到RestTemplate的拦截器集合里去,供后续使用

该配置类 初始化了SmartInitializingSingleton,通过回调方法对容器中的所有restTemplate进行定制,通过restTemplateCustomizer————>[就是增加一个拦截器LoadBalancerInterceptor]

通过查看LoadBalancerInterceptor 该bean在初始化的时候会把LoadBalancerClient作为初始化bean参数注入                                                                          [LoadBalancerClient是一个接口]

在该bean初始化时候,会将LoadBalancerClient注入进来,它的实现类是 RibbonLoadBalancerClient,那么它是在哪里实例化的呢?

在LoadBalancerClient的同级目录,根据猜测定位到  RibbonAutoConfiguration,在这里进行将LoadBalancerClient的实现类RibbonLoadBalancerClient初始化并将其放到容器当中去。

 在RibbonAutoConfiguration通过类上注解可看到一些重要信息,如图所述:

回到restTemplate.getForObject(url就是服务名+接口访问路径 )去通用订单服务,调用过程中会被

拦截器进行拦截,调用 LoadBalancerInterceptor.intercept()方法,方法里执行execute方法

 这里注意loadbalancer的实现类

在execute方法里首先会调用getLoadBalancer从容器中获取一个负载均衡器,那么ILoadBalancer

在哪里进行初始化的呢?[在同级目录下找找相关配置的类configuration]

                                                            图  ribbon.1 

最终在RibbonClientConfiguration里找到了初始化ILoadBalancer的实现ZoneAwareLoadBalancer

 找到了真正的负载均衡器ZoneAwareLoadBalancer,并将其从getLoadBalancer方法返回,回到图

ribbon.1  execute 方法,将loadBalancer向方法getServer(loadBalancer)传递

 该方法里面 通过负载均衡器会根据负载均衡算法挑选一个Server ,这里会先走负载均衡器BaseLoadBalancer类的chooseServer方法

 默认负载均衡规则会进入ZoneAvoidanceRule类,但是在该类里没有找到choose方法

发现在它的父类PredicateBasedRule找到了choose方法

 在choose里进到chooseRoundRobinAfterFiltering方法,真正的实现轮询的逻辑

                                                                图 ribbon.2 

在该方法可以看出底层就是从0开始,每次加1然后对实例列表取模得到实例的数组下标值。

 那么接下来分析负载均衡器ILoadBalancer  getAllServers() 是从哪里放进去的  [ 图 ribbon.3 ]

接下来看下负载均衡器初始化的地方,来到 RibbonClientConfiguration

 在初始化ZoneAwareLoadBalancer的时候会初始化两个父类

在BaseLoadBalancer父类调用了initWithConfig方法     

设置Server的定时Ping任务 

[ ribbin在真正通过ip+端口访问某一台机器时,会预先去注册中心检查一次服务是否存活[ UP或Down],不是活的话就换其他机器进行调用,ping的策略也有很多种,默认全局10s,局部变量30s覆盖10s]

 在初始化DynamicServerListLoadBalancer父类的时候,调用了restOfInit方法

在restOfInit方法里调用了这个方法enableAndInitLearnNewServersFeature,该方法会定时更新eureka-client端实例列表      [ 服务实例上线或者下线 ]   会走到该方法——>updateListOfServers

在updateListOfServers里最终会调用DiscoveryEnabledNIWSServerList类的

obtainServersViaDiscovery方法,同时设置到父类BaseLoadBalancer类的allServerList成员变量

在obtainServersViaDiscovery方法里,从eureka客户端缓存列表获取服务名称对应实例列表

 最终会把拿到的serverList放到BaseLoadBalancer类的allServerList成员变量里面

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Run,boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值