当前位置: 首页 > news >正文

【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服务,就会发现消耗的时间变短了:

相关文章:

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

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

Linux下基本指令(上)

文章内容: 1. ls 指令 语法: ls [选项][目录或文件] 功能:对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以及其他信息。 单个ls显示当前目录下的文件和目录 常用选项&#…...

C++ 并发编程实战 第十一章 多线程应用的测试和除错

目录 11.1 与并发相关的错误类型 11.1.1 不必要的阻塞 11.1.2 条件竞争 11.2 定位并发错误的技术 11.2.1 代码审阅——发现潜在的错误 11.2.2 通过测试定位并发相关的错误 11.2.3 可测试性设计 11.2.4 多线程测试技术 11.2.5 构建多线程测试代码 11.2.6 测试多线程代…...

Redis实现API访问频率限制

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

BGP服务器租用价格表_腾讯云PK阿里云

BGP云服务器像阿里云和腾讯云均是BGP多线网络,速度更快延迟更低,阿里云BGP服务器2核2G3M带宽优惠价格108元一年起,腾讯云BGP服务器2核2G3M带宽95元一年起,阿腾云分享更多云服务器配置如2核4G、4核8G、8核16G等配置价格表如下&…...

时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解

时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解 目录 时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 SSA-VMD麻雀搜索算法SSA优化VMD变分模态分解 可直接运行 分解效果好…...

【CSS如何实现双飞翼布局】

双飞翼布局是一种基于浮动布局的设计模式,主要用于实现三栏布局。它的主要特点是左右两列是浮动的,中间一列使用margin负值来达到“自适应”的效果。这种布局模式可以避免使用嵌套的div,同时也可以保证页面的语义结构清晰。以下是实现双飞翼布…...

服务注册发现机制

二、注册中心选型 1. zk和eureka的区别 zk:CP设计(强一致性),目标是一个分布式的协调系统,用于进行资源的统一管理。 当主节点crash后,需要进行leader的选举,在这个期间内,zk服务是不可用的(当然…...

【postgresql 基础入门】多表联合查询 join与union 并,交,差等集合操作,两者的区别之处

多表数据联合查询 ​专栏内容: postgresql内核源码分析手写数据库toadb并发编程 ​开源贡献: toadb开源库 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤&#x…...

很可惜,pyinstaller不是万能的

近期活不算少,但是真正新的东西很少,基本都是做些相似的功能,所以有精力想想之前悬而未决的问题,比如前两天写的加快软件启动速度的探索,这几天又想起一个之前没有解决的问题,这个问题之前也在博客写过&…...

0/1背包问题

例题HDU-2602 Problem Description Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … The bone collector had a big bag wi…...

Redis入门到精通——00数据类型

1、String 1.1、介绍 String 是最基本的 key-value 结构,key 是唯一标识,value 是具体的值,value其实不仅是字符串, 也可以是数字(整数或浮点数),value 最多可以容纳的数据长度是 512M 1.2、…...

PADS9.5使用记录

目录 一、概述 二、PADS Logic IN4148二极管封装 SOD-123封装 SOD-323封装 SOD-523封装 2N3904 1AM 三极管封装 78L05 7533-1 一、概述 PADS Logic 原理图绘制PADS Layout PCB 封装设计PADS Router 布线 二、PADS Logic …...

Axios post请求出现500错误

笔者在编写前端form表单传后端数据的时候,出现了以下问题 一、问题场景 当我用axios发送post请求的时候,出现了500错误 笔者找了很长时间错误,代码没问题,后端接口也没问题,后来发现问题出在实体类上了 当前端post请…...

【Leetcode】171.Excel 表列序号

一、题目 1、题目描述 给你一个字符串 columnTitle ,表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如: A -> 1 B -> 2 C -> 3 … Z -> 26 AA -> 27 AB -> 28 … 示例1: 输入: columnTitle = "A" 输出: 1示例2: 输入: colu…...

2023湖南省赛游记/题解

省赛拖了大哥们的后腿&#xff0c;感觉随便补个正常一队水平的人&#xff0c;我们一队肯定能AK。只能说自己真的菜&#xff0c;全程帮不上什么忙&#xff0c;还负贡献&#xff0c;真的想笑 B 暴力sg #include <bits/stdc.h> #define ll long long #define ull unsigned…...

海信电视U8KL使用体验:参数卷,画质技术也独有!

每个家庭成员对电视都有不同需求&#xff0c;如何能做到兼顾&#xff1f;看似需求众口难调&#xff0c;其实一台海信电视就能满足所有啦。 海信电视的参数不仅是最卷的&#xff0c;同时画质技术还是国内独有的&#xff0c;能把这样一台优秀的电视搬回家&#xff0c;无论电影、…...

E. Mishap in Club

题目&#xff1a; 样例1&#xff1a; 输入 --输出 1 样例2&#xff1a; 输入 --- 输出 3 思路&#xff1a; 数学贪心模拟思路&#xff0c;由于不知道在俱乐部的人数和在外面的人数&#xff0c;又要尽可能少的人数&#xff0c;那么定义两个变量&#xff0c;一个是里面的人数 i…...

UE4 自带体积云应用

新建空关卡 点击该选项 全部点击一遍 拖进场景...

RTP/RTCP 协议讲解

文章目录 前言一、RTP 协议1、RTP 协议概述2、RTP 工作机制3、RTP 协议的报文结构4、wireshark 抓取 RTP 报文 二、RTCP 协议1、RTCP 协议概述2、RTCP 工作机制3、RTCP 数据报4、wireshark 抓取 RTCP 报文 三、RTSP 和 RTP 的关系四、易混淆概念1、RTP over UDP 和 RTP over RT…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...