聊聊Ribbon源码解读之负载均衡

举报
周杰伦本人 发表于 2022/09/29 13:58:51 2022/09/29
【摘要】 聊聊Ribbon源码解读之负载均衡上篇文章我们说到RibbonLoadBalancerClient的execute()方法需要获取负载均衡器,这篇文章我们就看一下到底是怎么获取负载均衡器的。 负载均衡器深入getLoadBalancer()方法我们发现它就是调用SpringClientFactory的getInstance()方法获取的是ILoadBalancer的实例,那么ILoadBa...

聊聊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,它是在选择服务器时可以避开一个区域的负载均衡器。通过看这一段代码就水落石出了,ILoadBalancer实例是在RibbonAutoConfiguration类中定义的。

通过负载均衡器选择服务

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;
        }
    }
  1. 获取当前服务实例的索引值
  2. 通过求余数的方法记录下一个索引值
  3. 使用CAS,nextIndex和current相等的时候,设置值nextIndex为next
  4. 返回当前服务实例的索引值

这其实就是轮询操作的逻辑,轮询操作是常用的也就是比较简单的一种负载均衡策略。

执行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()方法

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。