Ribbon怎么实现的负载均衡

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
简介: Ribbon怎么实现的负载均衡

负载方案简介:

目前主流的负载方案分为以下两种:
1.集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)。
2.客户端自己做负载均衡,根据自己的请求情况做负载,Ribbon 就属于客户端自己做负载。

而Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API 网关那样需要独立部署,但是它几乎存在于每一个 Spring Cloud 构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过 Ribbon 来实现的

接下来就带大家通过几行源码的debug查看单机的Ribbon默认算法是实现的

1.工程中引入谷歌提供的guava工具类和Ribbon组件的依赖,
pom.xml:

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>30.1.1-jre</version>
    </dependency>

    <dependency>
        <groupId>com.netflix.ribbon</groupId>
        <artifactId>ribbon</artifactId>
        <version>2.2.2</version>
    </dependency>
    <dependency>
        <groupId>com.netflix.ribbon</groupId>
        <artifactId>ribbon-core</artifactId>
        <version>2.2.2</version>
    </dependency>
    <dependency>
        <groupId>com.netflix.ribbon</groupId>
        <artifactId>ribbon-loadbalancer</artifactId>
        <version>2.2.2</version>
    </dependency>

2.测试类:
public static void main(String[] args) {
// 注册两个server,顺序分别是8081,8082
List serverList = Lists.newArrayList(
new Server("localhost", 8081),
new Server("localhost", 8082)
);

    ILoadBalancer baseLoadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
    Server localhost = baseLoadBalancer.chooseServer("localhost");
    Server localhost2 = baseLoadBalancer.chooseServer("localhost");
    Server localhost3 = baseLoadBalancer.chooseServer("localhost");
    Server localhost4 = baseLoadBalancer.chooseServer("localhost");
    System.out.println(localhost);
    System.out.println(localhost2);
    System.out.println(localhost3);
    System.out.println(localhost4);

}
//代码效果参考:http://www.zidongmutanji.com/zsjx/464857.html

3.BoadBalancerBuilder.newBilder()源码逐行深入
// 这段代码是其核心,这里注册了默认的算法机制和choose的api
LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
接下来介绍我所认知的几个核心关键点

// 用来注册默认的负载均衡算法类,以配置类对象的形式初始化用到的属性
LoadBalancerBuilder.newBuilder()
具体流程:

3.1 执行newBilder()方法,进行创建"LoadBalancerBuilder"对象
在这里插入图片描述

3.2 点进去,在创建“LoadBalancerBuilder”对象时,会初始化其类属性,这里有个关键点,在第16行会执行一个配置默认参数值的属性,并且返回其配置类
在这里插入图片描述

3.3 此时会执行一个"default"默认的注册配置信息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4 进入this.loadDefaultValues()方法
在这里会看到一大坨默认的注册信息,核心参数:"NFLoadBalancerRuleClassName" 请记住这个字段

咱们这里只看有关默认算法的代码,其他的不做扩展

public void loadDefaultValues() {
xxxxxxxxxx
this.putDefaultStringProperty(CommonClientConfigKey.NFLoadBalancerRuleClassName, this.getDefaultNfloadbalancerRuleClassname());
xxxxxxxxxx
}
在这里插入图片描述

3.5 AvailabilityFilteringRule对象
他继承自ClientConfigEnabledRoundRobinRule对象 所以在后期创建的时候会执行其构造方法和类的属性。
在这里插入图片描述

3.6 看到这里我们就知道了,RIbbon的默认算法是轮询的算法机制。
在这里插入图片描述

  1. buildFixedServerListLoadBalancer(servers)源码逐行深入
    ILoadBalancer baseLoadBalancer =
             LoadBalancerBuilder
                     .newBuilder()
                         .buildFixedServerListLoadBalancer(serverList);
    
    4.1 点进去会看到 rule肯定是null,然后他会拿到刚刚解析的配置类进行从配置类信息中创建Rule的操作
    在这里插入图片描述

4.2 这里就看到我们在3.3中提到的”NFLoadBalancerRuleClassName“key拿到默认负载算法的Class对象。
在下面又通过ClientFactory.instantiateInstanceWithClientConfig(ruleClassName, config);方法进行className的实例化,拿到AvailabilityFilteringRule对象的实例,并且内部Rule默认为RoundRobinRule对象做负载均衡算法。
在这里插入图片描述
除了RoundRobinRule以外还有其他的算法
在这里插入图片描述

5.既然默认的算法机制搞清楚了 就可以进行choose server了
5.1 执行多个重载的choose方法
Server server = baseLoadBalancer.chooseServer();
往下直接看606行的choose方法
在这里插入图片描述

继续看choose方法
在这里插入图片描述
在点进去
在这里插入图片描述

5.2 执行增量取模算法
这里核心的方法是44行的"this.incrementAndGetModulo(serverCount);"方法,它通过你传入的server列表个数拿到负载均衡后的索引值。
在这里插入图片描述

算法实现是每次都拿这个AtomicInteger类型值做当前server数组的下标,每次choose都get出当前下标,进行+1再取模 达到雨露均沾的负载均衡效果,并且使用cas方式操作值的变化。

private AtomicInteger nextServerCyclicCounter;
在这里插入图片描述

5.3 算法执行完后进行检查处理
取出server后会进行server的检查判断:
1.如果server是null或者isAlive为false,则continue这次循环,继续下一次轮询
2.如果轮询次数超过10次,则会输入wran警告,并且返回null
log.warn("No available alive servers after 10 tries from load balancer: " + lb);

6.默认算法需要注意点
在这里插入图片描述

这里有意思的是,它内部算法先进行+1,然后就是1+1再%长度的运算。所以第一次取出来的就是server服务列表中的第二个server了...
存的顺序是8081,8082 默认取出来顺序是8082 8081 8082 8081

写到这里就结束了,基本是对默认的负载算法有一个流程的认识。如果不太了解Ribbon单机试玩版如何操作的话 看完可以帮助大家~

7.使用RxJava构建Ribbon
在结尾给大家附上一个通过RxJava实现的代码:

pom.xml:


io.reactivex
rxjava
1.0.10

Java:

// 服务列表
List serverList = Lists.newArrayList(new Server("localhost", 8081), new Server("localhost", 8083));
// 构建负载实例
ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
// 调用 5 次来测试效果
for (int i = 0; i < 5; i++) {
String result = LoadBalancerCommand.builder().withLoadBalancer(loadBalancer).build()
.submit(new ServerOperation() {
public Observable call(Server server) {
try {
String addr = "http://" + server.getHost() + ":" + server.getPort() + "/user/hello";
System.out.println(" 调用地址:" + addr);
URL url = new URL(addr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.connect();
InputStream in = conn.getInputStream();
byte[] data = new byte[in.available()];
in.read(data);
return Observable.just(new String(data));
} catch (Exception e) {
return Observable.error(e);
}
}
}).toBlocking().first();
System.out.println(" 调用结果:" + result);

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
1月前
|
负载均衡 Java Nacos
Ribbon负载均衡
Ribbon负载均衡
31 1
Ribbon负载均衡
|
4月前
|
负载均衡 算法 架构师
Ribbon负载均衡
上一节就已经实现的负载均衡笔者并未深入探讨,本节通过分析负载均衡算法、Ribbon实现负载均衡的底层原理和实现过程,让大家对负载均衡有了一个大体认识,同时针对Ribbon自定义负载均衡策略,饥饿加载让大家对于Ribbon的了解又多一些。Ribbon实现的负载均衡只是方案之一,我们可以尽量多了解但不要局限于此。
|
1月前
|
负载均衡 算法 Java
除了 Ribbon,Spring Cloud 中还有哪些负载均衡组件?
这些负载均衡组件各有特点,在不同的场景和需求下,可以根据项目的具体情况选择合适的负载均衡组件来实现高效、稳定的服务调用。
81 5
|
18天前
|
负载均衡 Java Nacos
常见的Ribbon/Spring LoadBalancer的负载均衡策略
自SpringCloud 2020版起,Ribbon被弃用,转而使用Spring Cloud LoadBalancer。Ribbon支持轮询、随机、加权响应时间和重试等负载均衡策略;而Spring Cloud LoadBalancer则提供轮询、随机及Nacos负载均衡策略,基于Reactor实现,更高效灵活。
42 0
|
3月前
|
负载均衡 Java Nacos
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
微服务介绍、SpringCloud、服务拆分和远程调用、Eureka注册中心、Ribbon负载均衡、Nacos注册中心
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
|
4月前
|
存储 设计模式 缓存
OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现
该文章主要介绍了如何在OpenFeign中集成Ribbon以实现负载均衡,并详细分析了Ribbon中服务选择和服务过滤的核心实现过程。文章还涉及了Ribbon中负载均衡器(ILoadBalancer)和负载均衡策略(IRule)的初始化方式。
OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现
|
4月前
|
缓存 负载均衡 Java
OpenFeign最核心组件LoadBalancerFeignClient详解(集成Ribbon负载均衡能力)
文章标题为“OpenFeign的Ribbon负载均衡详解”,是继OpenFeign十大可扩展组件讨论之后,深入探讨了Ribbon如何为OpenFeign提供负载均衡能力的详解。
OpenFeign最核心组件LoadBalancerFeignClient详解(集成Ribbon负载均衡能力)
|
5月前
|
负载均衡 算法 网络协议
Ribbon 负载均衡源码解读
Ribbon 负载均衡源码解读
64 15
Ribbon 负载均衡源码解读
|
3月前
|
负载均衡 Java 开发者
Ribbon框架实现客户端负载均衡的方法与技巧
Ribbon框架为微服务架构中的客户端负载均衡提供了强大的支持。通过简单的配置和集成,开发者可以轻松地在应用中实现服务的发现、选择和负载均衡。适当地使用Ribbon,配合其他Spring Cloud组件,可以有效提升微服务架构的可用性和性能。
42 0
|
5月前
|
负载均衡 Java API
Feign 进行rpc 调用时使用ribbon负载均衡源码解析
Feign 进行rpc 调用时使用ribbon负载均衡源码解析
80 11
下一篇
DataWorks