聊聊Ribbon源码解读之负载均衡
Posted 周杰伦本人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊聊Ribbon源码解读之负载均衡相关的知识,希望对你有一定的参考价值。
聊聊Ribbon源码解读之负载均衡
上篇文章我们说到RibbonLoadBalancerClient的execute()方法需要获取负载均衡器
负载均衡器
深入getLoadBalancer()方法我们发现它就是调用SpringClientFactory的getInstance()方法获取的是ILoadBalancer的实例,那么ILoadBalancer实例是在哪里定义的呢?
我们再看RibbonAutoConfiguration类
@Bean
public SpringClientFactory springClientFactory()
SpringClientFactory factory = new SpringClientFactory();
factory.setConfigurations(this.configurations);
return factory;
这里定义了SpringClientFactory类,它的构造方法中使用了RibbonClientConfiguration类,RibbonClientConfiguration中定义了ILoadBalancer的实现类ZoneAwareLoadBalancer,它是在选择服务器时可以避开一个区域的负载均衡器。
通过负载均衡器选择服务
getServer()方法中调用ILoadBalancer实例的chooseServer(); ILoadBalancer实例我们分析是ZoneAwareLoadBalancer
这里的判断getLoadBalancerStats().getAvailableZones().size()默认是1,所以会执行父类BaseLoadBalancer的chooseServer()方法,这里用到的IRule来进行选择服务,通过RibbonClientConfiguration中的IRule接口的注入,可以知道是ZoneAvoidanceRule,而ZoneAvoidanceRule没有重写choose()方法,而是使用父类PredicateBasedRule的choose()方法,从过滤后的服务列表中选择一个服务,具体是incrementAndGetModulo()方法:
private int incrementAndGetModulo(int modulo)
for (;;)
int current = nextIndex.get();
int next = (current + 1) % modulo;
if (nextIndex.compareAndSet(current, next) && current < modulo)
return current;
- 获取当前服务实例的索引值
- 通过求余数的方法记录下一个索引值
- 使用CAS,nextIndex和current相等的时候,设置值nextIndex为next
- 返回当前服务实例的索引值
这其实就是轮询操作
执行RibbonLoadBalancerClient的execute()方法
execute()方法中的关键代码是request.apply(serviceInstance);
request是LoadBalancerRequest的实例,而通过拦截器LoadBalancerInterceptor调用this.loadBalancer.execute(),LoadBalancerRequest实例的生成是通过LoadBalancerRequestFactory 的createRequest()生成的 ,最终调用了AbstractClientHttpRequest的execute()方法,
而我们使用restTemplate.getForObject()进行远程调用的时候,也是调用了AbstractClientHttpRequest的execute()方法
总结
这篇文章主要解读了RibbonLoadBalancerClient的execute()方法中的三个重要步骤:获取负载均衡器、选取服务、执行execute()方法,其中负载均衡器是ZoneAwareLoadBalancer,选取服务是通过轮询机制,然后执行执行RibbonLoadBalancerClient的execute()方法
以上是关于聊聊Ribbon源码解读之负载均衡的主要内容,如果未能解决你的问题,请参考以下文章