【Spring Cloud】Ribbon 实现负载均衡的原理,策略以及饥饿加载

文章目录

  • 前言
  • 一、什么是 Ribbon
  • 二、Ribbon 实现负载均衡的原理
    • 2.1 负载均衡的流程
    • 2.2 Ribbon 实现负载均衡的源码剖析
  • 三、Ribbon 负载均衡策略
    • 3.1 负载均衡策略
    • 3.2 演示 Ribbon 负载均衡策略的更改
  • 四、Ribbon 的饥饿加载
    • 4.1查看 Ribbon 的懒加载
    • 4.2 Ribbon 的饥饿加载模式


前言

在前文《深入理解 Eureka 注册中心的原理、服务的注册与发现》中,介绍了如何使用 Eureka 实现服务的注册与拉取,并且通过添加 @LoadBalanced 注解实现了负载均衡。这种自动化的背后隐藏着许多疑问:

  • 服务是在何时进行拉取的?
  • 负载均衡是如何实现的?
  • 负载均衡的原理和策略又是什么?

本文旨在深入探讨使用 Eureka 实现负载均衡的原理,为我们理解微服务架构中服务调用的内部机制提供更清晰的认识。通过解答这些疑惑,我们将更好地理解服务发现、负载均衡的运作方式,为构建高性能、稳定的分布式系统打下坚实的基础。

一、什么是 Ribbon

Ribbon 是一个基于 HTTP 和 TCP 客户端的负载均衡器。在微服务架构中,服务的调用通常涉及到负载均衡的问题,即在多个服务提供方中选择一个进行调用。Ribbon 提供了一种简单而有效的负载均衡解决方案。

Ribbon 最初是 Netflix 公司开发的,后来成为 Spring Cloud 项目的一部分。它的主要作用是在服务消费者和提供者之间实现均衡的流量分发,确保每个服务提供者都能够得到适当的请求,避免出现服务过载或资源浪费的情况。

具体而言,Ribbon 实现了以下功能:

  1. 负载均衡算法: Ribbon 支持多种负载均衡算法,例如轮询、随机、权重轮询等,使得服务消费者可以根据实际场景选择适当的负载均衡策略。

  2. 服务实例的自动发现: Ribbon 与 Eureka 等服务注册中心集成,能够自动获取可用的服务实例列表。

  3. 故障转移和重试机制: Ribbon 具备故障转移和重试功能,可以在服务提供者发生故障时自动切换到其他健康的实例,提高系统的稳定性和可用性。

在 Spring Cloud 中,Ribbon 作为一个负载均衡的客户端组件,通过拦截微服务的调用请求,动态地选择目标服务实例,从而分配请求的负载,实现了对服务调用的细粒度控制。

二、Ribbon 实现负载均衡的原理

2.1 负载均衡的流程

Ribbon 实现负载均衡的流程图如下:
负载均衡流程

下面是对这个流程的详细说明:

  1. 首先,服务消费者发起请求,Ribbon 负载均衡器收到请求之后,获取请求路径中的服务名称,例如 userservice
  2. 然后负载均衡器使用这个获取到的服务名称去向 Eureka Service 拉取对应的服务。
  3. 在实际生产中,一个服务一般都会有多个实例,因此拉取到的就是一个服务列表,列表中包含了这个服务所有正常实例的 IP 和端口号。
  4. 负载均衡器在获取到这个列表之后,使用当前采取的负载均衡策略去选择一个合适的服务,然后再访问这个服务。

这个流程确保了服务的请求能够被合理地分发到多个实例中,从而实现了负载均衡。

2.2 Ribbon 实现负载均衡的源码剖析

首先,Ribbon 实现负载均衡使用到的一个类叫做 LoadBalancerInterceptor负载均衡拦截器,可以通过 IDEA 查看它的源码:


发现它实现了一个 ClientHttpRequestInterceptor接口,即客户端 HTTP 请求拦截器:

它会拦截 RestTemplate 发生的 HTTP 请求,ClientHttpRequestInterceptor 是一个接口,并且其中包含了一个 intercept 方法,因此LoadBalancerInterceptor 作为实现这个接口的类也一定重写了 intercept 方法,此时我们可以在这个方法中设置一个断点进行调试,以追踪代码的运行:

  1. request.getURI() 获取请求地址:

  2. originalUri.getHost() 获取到了请求的地址中的主机名,此时获取到的就是服务的名称,也就是 userservice


3. 当找到了服务的名称之后,接下来要做的工作就是向 EurekaServer 去拉取对应的服务了,然后这个方法就把获取到的服务名交给了一个RibbonLoadBalancerClient (Ribbon负载均衡客户端)进行处理。

4. 继续调试代码,进入execute 方法:


  1. 继续往下走,就得到了一个 LoadBalancer 对象,:

    这个对象的名称叫做“动态服务列表均衡器”,查看这个对象的内容,可以发现服务列表中服务的数量为3,这三个服务就是获取到的三个 user-service 向 EurekaServer 中注册的服务。

因此getLoadBalancer 方法的作用就是根据服务名称向 EurekaServer 中寻找服务列表。当找到了服务列表之后,我们就可以大胆的猜测,下一步所要做的工作就是进行负载均衡操作了。

  1. 此时,我们进入 getServer 方法:

  2. 接下来就调用了chooseServer 方法,进入这个方法:

在这里插入图片描述

8. 然后再进入chooseServer 方法,最后找到了rule.choose方法:

此时查看 rule 对象,发现是一个接口:

既然是接口,那么就有实现类:

此时发现的实现类就是负载均衡的规则了。大致的规则有随机、轮询等等。

  1. 最后,通过默认的规则,就选择到了 8082 这个端口的服务了。


接下来就可以使用真正的IP和端口号去代替 userservice ,然后去访问指定了服务了。

以上就是 Ribbon 实现负载均衡的源码剖析,通过调试了方法深入探索了服务发现与负载均衡是实现流程,帮助我们更好的理解了服务发现、负载均衡的运作方式

三、Ribbon 负载均衡策略

3.1 负载均衡策略

通过上面的源码分析不难发现,Ribbon 的负载均衡规则是一个叫做 IRule 的接口来定义的,每一个子接口都是一种规则。

关于 IRule 接口的继承体系如下图所示:

关于 Ribbon 的负载均衡策略可以总结如下表所示:

内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对短路和并发数过高的服务器进行忽略
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器
RetryRule重试机制的选择逻辑

Ribbon 提供了这些内置的负载均衡规则,同时也支持自定义负载均衡规则。在实际应用中,根据业务特点选择合适的负载均衡策略是非常重要的。下面演示了 Ribbon 负载均衡策略的更改。

3.2 演示 Ribbon 负载均衡策略的更改

通过定义IRule实现可以修改负载均衡规则,有两种方式:

  1. 代码方式:在order-service中的OrderApplication启动类中,定义一个新的IRule,并使用 @Bean 注解注册到 Spring 容器中:
@Bean
public IRule randomRule(){return new RandomRule();
}
  1. 配置文件方式:在order-serviceapplication.yml文件中,添加新的配置也可以修改规则:
# 修改 Ribbon 负载均衡策略
userservice:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则

例如,下面是修改了负载均衡策略之后,再次使用 order-service 访问订单的结果。可以发现,现在不再是以轮询的方式挑选user-service服务了,而是以随机的方式进行挑选了。

四、Ribbon 的饥饿加载

4.1查看 Ribbon 的懒加载

当我们重新启动 order-service 服务,然后在浏览器中进行订单访问,可以发现如下的现象:

order-service 服务启动后,第一次访问服务可以发现耗时需要三百多毫秒:


然后,再次访问多次,可以发现耗时都变成了十几毫米:


通过以上的现象就可以发现,Ribbon 默认采用的是懒加载模式,就像单例模式的懒汉模式一样,第一次访问的时候才会去创建LoadBalanceClient实例,请求时间会很长。

4.2 Ribbon 的饥饿加载模式

为了解决上述懒加载的耗时问题,Ribbon 还提供了饥饿加载模式,饥饿加载则会在项目启动时创建,降低第一次访问的耗时。

通过下面配置开启饥饿加载:

此时重启 order-service服务:

在启动服务的时候,就会发现日志变得更多了:

这个日志的内容就是加载LoadBalanceClient实例所产生的日志。

再次首次访问 order-service服务,就会发现消耗的时间变短了:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/146881.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python无废话-办公自动化Excel修改数据

如何修改Excel 符合条件的数据?用Python 几行代码搞定。 需求:将销售明细表的产品名称为PG手机、HW手机、HW电脑的零售价格分别修改为4500、5500、7500,并保存Excel文件。如下图 Python 修改Excel 数据,常见步骤: 1&…

Ubuntu20 QT6.0 编译 ODBC 驱动

一、新建测试项目 新建一个控制台项目&#xff0c; // main.cpp #include <QCoreApplication> #include <QSqlDatabase> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 获取当前Qt支持的驱动列表QStringList driv…

1300*C. Coin Rows(枚举模拟)

解析&#xff1a; 两人都绝对聪明&#xff0c;Alice先走&#xff0c;尽量让Bob所能拿的分数最少&#xff0c;Alice有一次往下走的机会&#xff0c;剩余没走过的点正好分为两断断开的区域&#xff0c;所以Bob的最大分数要么在第一格向下或者在最后一列向下。 遍历区间&#xff0…

stm32之1602+DHT11+继电器

描述&#xff1a; 1、DHT11监测温室度&#xff0c;并显示到1602液晶上 2、通过串口打印&#xff08;或通过蓝牙模块在手机上查看&#xff09; 3、当温度大于24度时&#xff0c;开启继电器。小于时关闭继电器&#xff08;继电器可连接风扇---假想O(∩_∩)O哈哈~&#xff09; 一、…

软件测试基础学习

注意&#xff1a; 各位同学们&#xff0c;今年本人求职目前遇到的情况大体是这样了&#xff0c;开发太卷&#xff0c;学历高的话优势非常的大&#xff0c;公司会根据实际情况考虑是否值得培养&#xff08;哪怕技术差一点&#xff09;&#xff1b;学历稍微低一些但是技术熟练的…

画CMB天图使用Planck配色方案

使用Planck的配色方案&#xff1a; 全天图&#xff1a; 或者方形图&#xff1a; 使用下面设置即可&#xff1a; import pspy, pixell from pspy.so_config import DEFAULT_DATA_DIR pixell.colorize.mpl_setdefault("planck")此方法不会改变matplotlib默认配色方案…

zemax场曲/畸变图与网格畸变图

网格畸变是XY两个方向上的几何畸变&#xff0c;是不同视场实际像高与近轴像高的偏差。 垂轴放大率在整个视场范围内不能保持常数 当一个有畸变的光学系统对一个方形的网状物体成像时,若δy>0&#xff0c;则主光线的交点高度y比理想像高y低,视场越大&#xff0c;低得越多&a…

Xmake v2.8.3 发布,改进 Wasm 并支持 Xmake 源码调试

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它非常的轻量&#xff0c;没有任何依赖&#xff0c;因为它内置了 Lua 运行时。 它使用 xmake.lua 维护项目构建&#xff0c;相比 makefile/CMakeLists.txt&#xff0c;配置语法更加简洁直观&#xff0c;对新手非常友好&#x…

知识工程---neo4j 5.12.0+GDS2.4.6安装

&#xff08;已安装好neo4j community 5.12.0&#xff09; 一. GDS下载 jar包下载地址&#xff1a;https://neo4j.com/graph-data-science-software/ 下载得到一个zip压缩包&#xff0c;解压后得到jar包。 二. GDS安装及配置 将解压得到的jar包放入neo4j安装目录下的plugi…

CTP:关于cc和bindgen库及rust工程组织

有三个工程目录&#xff0c;cpt-api, ctp-sdk,ctp-strategy 1、ctp-sdk&#xff1a; 主要的目的是基于bindgen库生成与cpp的.h文件相对应一个binding.rs文件&#xff0c;后面供策略使用。 在这个目录下&#xff0c;建一个build.rs,用bindgen库生成cpp.h的头文件相应的rust绑定…

Cortex-A9 架构

一、Cortex-A 处理器运行模式 Cortex-A9处理器有 9中处理模式&#xff0c;如下表所示&#xff1a; 九种运行模式 在上表中&#xff0c;除了User(USR)用户模式以外&#xff0c;其它8种运行模式都是特权模式&#xff0c;在特权模式下&#xff0c;程序可以访问所有的系统资源。这…

spark SQL 任务参数调优1

1.背景 要了解spark参数调优&#xff0c;首先需要清楚一部分背景资料Spark SQL的执行原理&#xff0c;方便理解各种参数对任务的具体影响。 一条SQL语句生成执行引擎可识别的程序&#xff0c;解析&#xff08;Parser&#xff09;、优化&#xff08;Optimizer&#xff09;、执行…

数据分析:数据分析篇

文章目录 第一章 科学计算库Numpy1.1 认识Ndarray1.2 Ndarray的属性1.3 Numpy中的数据类型1.4 Numpy数组1.4.1 Numpy数组的创建1.4.2 Numpy数组的基本索引和切片1.4.3 Numpy布尔索引1.4.4 数组运算和广播机制1.4.5 Numpy数组的赋值和Copy复制1.4.6 Numpy数组的形状变换1.4.7 Nu…

【ROS入门】使用 ROS 动作(Action)机制实现目标请求、进度与完成结果的反馈

文章结构 任务要求话题模型实现步骤定义action文件按照固定格式创建action文件编辑配置文件编译生成中间文件 编写服务端和客户端vscode配置服务端客户端编译配置文件执行 任务要求 使用 ROS 动作(Action)机制实现目标请求、进度与完成结果的反馈&#xff1a; 创建服务端&…

推荐算法——Apriori算法原理

0、前言&#xff1a; 首先名字别读错&#xff1a;an pu ruo ao rui 【拼音发音】Apriori是一种推荐算法推荐系统&#xff1a;从海量数据中&#xff0c;帮助用户进行信息的过滤和选择。主要推荐方法有&#xff1a;基于内容的推荐、协同过滤推荐、基于关联规则的推荐、基于知识的…

leetCode 53.最大子数和 图解 + 贪心算法/动态规划+优化

53. 最大子数组和 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入…

字符串,字符数组,类型转换,整数越界,浮点数,枚举

目录 自动类型转换 强制类型转换 数据类型 sizeof 数据类型所占字节数 整数越界 浮点数 字符型 字符串变量 ​编辑字符串的输入输出 main函数的参数 &#xff0c;argc,argv 单个字符输入输出 putchar getchar strlen,strcmp,strcat,strchr,strstr strlen 求字…

BASH shell脚本篇4——函数

这篇文章介绍下BASH shell中的函数。之前有介绍过shell的其它命令&#xff0c;请参考&#xff1a; BASH shell脚本篇1——基本命令 BASH shell脚本篇2——条件命令 BASH shell脚本篇3——字符串处理 函数是代码重用的最重要方式。Bash函数可以定义为一组命令&#xff0c;在b…

【STM32 CubeMX】移植u8g2(一次成功)

文章目录 前言一、下载u8g2源文件二、复制和更改文件2.1 复制文件2.2 修改文件u8g2_d_setup文件u8g2_d_memory 三、编写oled.c和oled.h文件3.1 CubeMX配置I2C3.2 编写文件oled.holed.c 四、测试代码main函数测试代码 总结 前言 在本文中&#xff0c;我们将介绍如何在STM32上成…

电脑显示系统错误怎么办?

有时我们在开机时会发现电脑无法开机&#xff0c;并显示系统错误&#xff0c;那么这该怎么办呢&#xff1f;下面我们就一起来了解一下。 方法1. 替换SAM文件解决问题 1. 重启电脑并进入安全模式。 Win8/10系统&#xff1a;在启动电脑看到Windows标志时&#xff0c;长按电源键…