Ribbon怎么实现的负载均衡

简介: 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);

相关文章
|
3月前
|
负载均衡 算法 架构师
Ribbon负载均衡
上一节就已经实现的负载均衡笔者并未深入探讨,本节通过分析负载均衡算法、Ribbon实现负载均衡的底层原理和实现过程,让大家对负载均衡有了一个大体认识,同时针对Ribbon自定义负载均衡策略,饥饿加载让大家对于Ribbon的了解又多一些。Ribbon实现的负载均衡只是方案之一,我们可以尽量多了解但不要局限于此。
|
1天前
|
负载均衡 Java Nacos
|
2月前
|
负载均衡 Java Nacos
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
微服务介绍、SpringCloud、服务拆分和远程调用、Eureka注册中心、Ribbon负载均衡、Nacos注册中心
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
|
3月前
|
存储 设计模式 缓存
OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现
该文章主要介绍了如何在OpenFeign中集成Ribbon以实现负载均衡,并详细分析了Ribbon中服务选择和服务过滤的核心实现过程。文章还涉及了Ribbon中负载均衡器(ILoadBalancer)和负载均衡策略(IRule)的初始化方式。
OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现
|
3月前
|
缓存 负载均衡 Java
OpenFeign最核心组件LoadBalancerFeignClient详解(集成Ribbon负载均衡能力)
文章标题为“OpenFeign的Ribbon负载均衡详解”,是继OpenFeign十大可扩展组件讨论之后,深入探讨了Ribbon如何为OpenFeign提供负载均衡能力的详解。
OpenFeign最核心组件LoadBalancerFeignClient详解(集成Ribbon负载均衡能力)
|
2月前
|
负载均衡 Java 开发者
Ribbon框架实现客户端负载均衡的方法与技巧
Ribbon框架为微服务架构中的客户端负载均衡提供了强大的支持。通过简单的配置和集成,开发者可以轻松地在应用中实现服务的发现、选择和负载均衡。适当地使用Ribbon,配合其他Spring Cloud组件,可以有效提升微服务架构的可用性和性能。
31 0
|
4月前
|
负载均衡 算法 网络协议
Ribbon 负载均衡源码解读
Ribbon 负载均衡源码解读
59 15
Ribbon 负载均衡源码解读
|
4月前
|
负载均衡 Java API
Feign 进行rpc 调用时使用ribbon负载均衡源码解析
Feign 进行rpc 调用时使用ribbon负载均衡源码解析
71 11
|
5月前
|
缓存 负载均衡 Java
Java一分钟之-Spring Cloud Netflix Ribbon:客户端负载均衡
【6月更文挑战第9天】Spring Cloud Netflix Ribbon是客户端负载均衡器,用于服务间的智能路由。本文介绍了Ribbon的基本概念、快速入门步骤,包括添加依赖、配置服务调用和使用RestTemplate。此外,还讨论了常见问题,如服务实例选择不均、超时和重试设置不当、服务列表更新不及时,并提供了相应的解决策略。最后,展示了如何自定义负载均衡策略。理解并正确使用Ribbon能提升微服务架构的稳定性和效率。
191 3
|
6月前
|
负载均衡
【SpringCloud】Ribbon负载均衡原理、负载均衡策略、饥饿加载
【SpringCloud】Ribbon负载均衡原理、负载均衡策略、饥饿加载
79 0