【SpringCloud】Eureka基于Ribbon负载均衡的调用链路流程分析

news2024/10/5 12:58:25

文章目录

    • 前言
    • 1.调用形式
    • 2.LoadBalancerInterceptor
    • 3.负载均衡流程分析
      • 3.1 调用流程图
      • 3.2 intercept()方法
      • 3.3 execute()方法
      • 3.4 getServer()方法
      • 3.4 子类的chooseServer()方法
      • 3.5 getLoadBalancerStats().getAvailableZones().size() <= 1
      • 3.6 父类的chooseServer()方法
      • 3.7 IRule接口下的实例
      • 3.8 最终的choose()方法—return server
      • 3.9 choose()方法内部分析
    • 4. 彩蛋

前言

微服务间相互调用的基础上,服务间的调用更多是以调用某多实例服务下的某个实例的形式。而这就需要用到负载均衡技术。对于开发者而言,只要通过@LoadBalance注解就开启了负载均衡。如此简单的操作底层究竟是什么样的,我想你也很想知道。

1.调用形式

在《SpringCloud集成Eureka并实现负载均衡》的基础之上,我们可以进行一个小小的实验,debug运行程序,通过postman发起一个请求,A服务会去远程调用B服务,debug发现发送的url为:http://user-service/user/1,毫无疑问的是,这就是A调用B的途径
在这里插入图片描述
同样地,拿到这个url我们去postman里发送请求:
在这里插入图片描述
发现请求无法发送出去,路径出了问题。观察路径中的参数user-service发现他是B服务的服务名称,那为什么在A服务里向B服务发送“服务名称-接口路径-参数”形式的请求就能够正常响应?
结合集成负载均衡的过程,这一定是Ribbon在发挥作用

2.LoadBalancerInterceptor

负载均衡的前提不是传递一个具体的url,肯定是Ribbon做了某种解析,通过服务名称得到了服务下的实例列表,从而拉取Eureka-Server中的服务注册表来将请求映射到指定的某个实例上。
结合曾经前后端分离的web开发经验,后端经常会在拦截器中拦截前端发来的请求来对请求做一些操作,比如校验、拼接、鉴权…调用方发送请求和接收方收到的请求并不一致,这其中会不会也是有一个类似于拦截器的东西拦截了请求,并且转换了请求呢?
答案是必然的,那是谁——LoadBalancerInterceptor
在这里插入图片描述
可以看到的是,他实现了ClientHttpRequestInterceptor接口,具体用法细节直接去看接口中声明的方法
直观的看出接口中声明了一个intercept()方法并且接受了HttpRequest参数来拦截了客户端的http请求,并且修改的请求体!这么一看URL更改的谜底就在此处揭晓了,那么方法底层具体是怎么实现的呢:

3.负载均衡流程分析

3.1 调用流程图

Debug源码之前先来看一下源码中的调用链路总体流程图(手图):
在这里插入图片描述
概括来看则是:拦截请求—读取服务—拉取服务列表—选择规则—返回服务实例

3.2 intercept()方法

下面我们开始Debug:
1.当发送请求使得服务间发生调用关系,调用请求会先传递到拦截器中的intercept方法,可以看到的是目前还和发送是保持一致
在这里插入图片描述
2.继续向下执行,开始解析请求,拿到了请求中的URI——通过getHost()方法拿到了主机地址(服务的名称)
在这里插入图片描述

3.3 execute()方法

3.Ribbon开始做负载均衡处理
在这里插入图片描述
4.两次步入之后进入到execute()方法内部,发现传递进来的服务名称作为服务Id进入到了getLoadBalance()方法,并且得到了一个ILoadbalance接口对象,而在该对象中封装了很多的信息:
在这里插入图片描述
这里记住服务实例id的值:host.docker.internal:8084,这就是Eureka客户端接收到的实例信息

3.4 getServer()方法

5.接口对象作为参数传递到了getServer()方法,得到了一个server对象进入到方法内部。发现与此同时传递了一个Object类型的对象用于指定服务器的规则或条件,不过到目前为止,这个参数一直都是null作为传递,即loadBalancer.chooseServer()方法采用的是‘default’的方式进行选择
在这里插入图片描述

3.4 子类的chooseServer()方法

6.再次步入到chooseServer()方法,发现是在一个名为BaseLoadBalancer类(这个类是负载均衡器的具体实现后面会具体分析)下重写的父类方法
此时:可以判断的是getLoadBalancerStats().getAvailableZones().size() <= 1为TRUE
在这里插入图片描述

3.5 getLoadBalancerStats().getAvailableZones().size() <= 1

对于表达式:getLoadBalancerStats().getAvailableZones().size() <= 1进行分析
发现在BaseLoadBalancer类中通过继承抽象类AbstractLoadBalancer并重写getLoadBalancerStats()抽象方法,获取到了一个loadbalancer统计信息集合LoadBalancerStats
在这里插入图片描述
在这里插入图片描述
而封装在LoadBalancerStats中的信息里有一个ConcurrentHashMap类型的集合属性,即

volatile Map<String, List<? extends Server>> upServerListZoneMap = new ConcurrentHashMap<String, List<? extends Server>>();

用于存储可用的服务列表,这个集合中的每个条目都代表一个区域,键是区域名称,值是该区域下可用服务器的列表。
在这里插入图片描述
后续的.getAvailableZones()方法则是获取这一属性值中所有的键,也就是可用的服务区域,并作为Set集合返回来进行判断
在这里插入图片描述
很显然,这里进一步论证getLoadBalancerStats().getAvailableZones().size() <= 1是为true的,后续就会去调用父类的chooseServer()方法

3.6 父类的chooseServer()方法

7.步入到父类的chooseServer()方法中,发现最后返回了一个Server类型的对象,这肯定就是具体的服务实例信息了。
在这里插入图片描述

3.7 IRule接口下的实例

去追踪rule变量,发现是一个IRule接口的实例,即为负载均衡提供规则的接口
在这里插入图片描述
并且此接口下有大量的规则实现,而默认的规则方式则为轮询调度
在这里插入图片描述
可是看到上图在debug时,rule变量右侧灰色显示的是rule:RandomRule@12045这是因为我通过配置IRule类型的Bean指定了负载均衡的规则:

    @Bean
    public IRule randomRule() {
        return new RandomRule();
    }

只要把他注释掉,程序就会继续去采用默认的规则即RoundRobinRule

3.8 最终的choose()方法—return server

8.了解了IRule接口的rule实例,再去看他最终调用的choose()方法。同样地步入进去,由于是默认规则,则按照流程进入到了RoundRobinRule规则实现中的choose方法(其实IRule接口下的每一个规则实现类都有choose方法)
在这里插入图片描述
实现了ILoadBalancer接口的负载均衡器对象作为参数传递到了方法中,与此同时key为default。开始为随机选择预热。

3.9 choose()方法内部分析

9.进入到while循环中,不断选择服务器,直到找到一个可用的服务器。随后会判断线程是否中断,如果中断了,则直接返回null。
在这里插入图片描述
这样的情况出现频率还是很高,由此可见,这个小设计会减少很多不必要计算,提升了程序运行的效率。
而后这是分别获取两个服务列表在这里插入图片描述
从列表中选择一个
在这里插入图片描述
兜底操作,对选择的做判断在这里插入图片描述
最后成功返回Server实例给chooseServer()方法,服务发起者发送http://user-service/user请求通过Ribbon最后轮询到了localhost:8084服务实例上

4. 彩蛋

现在有很多公司都在用Nacos替换Eureka,因为感知服务列表的变化不够敏感,感知下线服务太过迟钝,就像下面这种情况:
在这里插入图片描述
服务实例已经下线,时间大约过了一分钟,却还是把下线的服务加载到了可用服务列表里(upList),其实这并不怪Ribbon,都是Eureka的错
针对这种情况我们留个彩蛋,下次再来talk about~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低代码平台全解析:衍生历程、优势呈现与未来趋势一览无余

在数字化时代&#xff0c;应用程序的开发与更新已成为企业保持竞争力的关键。传统的编码方式&#xff0c;虽然精细且功能强大&#xff0c;但耗时且要求开发者具备较高的技术水平。在这样的背景下&#xff0c;低代码开发平台的出现无疑为企业带来了福音。 低代码开发平台是一种创…

一文全面了解低代码

目录 一、低代码概况 二、低代码构成 三、低代码开发者 1&#xff09;低代码赋能IT技术人员--低代码 2&#xff09;低代码赋能业务人员--零代码 四、低代码核心技术概念 五、低代码能力 六、低代码技术应用价值及趋势 一、低代码概况 2014年&#xff0c;Forrester提出了低代码…

nvm的下载与使用

1.如果已经安装nodejs , 先卸载nodejs; 从控制面板中 卸载程序 卸载nodejs win r打开cmd ,管理员运行 where node 查看是否删除干净nodejs 2.下载nvm 从github 下载nvm , 下载nvm 3.nvm 和node安装路径最好写在同一个路径下 &#xff0c;如D盘 ,D\a\nvm , D\a\nodejs 4.…

采购组件修改申请办理流程

现有采购流程1 #mermaid-svg-qAesAhfW2IQBcef8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-qAesAhfW2IQBcef8 .error-icon{fill:#552222;}#mermaid-svg-qAesAhfW2IQBcef8 .error-text{fill:#552222;stroke:#5522…

Linux:安装MySQL服务(非docker方式)

1、下载安装包 下载MySQL安装包&#xff0c;需要Oracle官网的账号 下面是网友提供的账号及密码&#xff0c;亲测有效。 账户&#xff1a;3028064308qq.com 我用的这个&#xff0c;可以登陆 密码&#xff1a;OraclePassword123!Oracle Account: 602205528qq.com Oracle Pass…

【原创】CentOS7.9解决mdadm组raid阵列后resync非常慢的问题

前言 前几日我买了4块16TB的硬盘使用mdadm组了一个raid10阵列&#xff0c;具体如何搭建的可以看我之前的博客。 【报错记录】疯狂踩坑之RockyLinux创建Raid1镜像分区&#xff0c;Raid分区在重启后消失了&#xff01;外加华硕主板使用Raid模式后&#xff0c;硬盘在系统中无法找…

查询数据库DQL

DQL 查询基本语法 -- DQL :基本语法; -- 1查询指定的字段 name entrydate 并返回select name , entrydate from tb_emp;-- 2 查询 所有字段 并返回select id, username, password, name, gender, image, job, entrydate, create_time, update_time from tb_emp;-- 2 查询…

【技巧】Word和Excel如何互相转换?

Word文档里有数据表格&#xff0c;如果编辑修改起来感觉没那么方便或容易出错&#xff0c;不妨将文档转换成Excel表格再来处理。 将Word文档转换成Excel&#xff0c;比较常用的是复制粘贴方法&#xff0c;也就是将Word文档的表格复制后&#xff0c;再粘贴到Excel表格里&#x…

STM32开发(三十)STM32F103 数据手册 —— 模拟/数字转换 DAC 详解

文章目录 DAC主要特征DAC内部框图单DAC通道数据格式DAC转换流程DAC输出电压计算方式选择DAC触发方式数字/模拟转换模块(DAC)是12位数字输入,电压输出的数字/模拟转换器。 DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。 DAC工作在12位模式时,数据可以设置成左对齐…

实力认证|易知微上榜中国信息通信研究院数字孪生城市产业图谱!

近期&#xff0c;中国通信院就数字孪生技术在城市层面的广泛应用&#xff0c;根据数字孪生产业框架&#xff0c;结合产业发展动态和企业综合实力评估&#xff0c;选取了核心产业、关联产业和辐射产业等各领域业务代表性较强的企业&#xff08;机构&#xff09;&#xff0c;形成…

如何使用$APPEALS法,分析用户期待?

$APPEALS分析法是一种用于分析用户期待和需求的方法&#xff0c;它可以帮助企业全方位多角度地了解客户对产品的期望&#xff0c;有助于企业多维度有侧重地调整市场规划和产品改进策略&#xff0c;帮助企业打造优势产品&#xff0c;提高市场竞争力。 下面是使用$APPEALS分析法来…

【以图会意】操作系统的加载流程

声明&#xff1a;本图为博主方便自己记忆理解&#xff0c;诸多疏漏望请博友理性观看&#xff01;如有错误不足恳请指正。 首先&#xff0c;操作系统是一段程序&#xff0c;他保存在ROM中&#xff0c;在开机时&#xff0c;CPU被激活&#xff0c;首先将IR置为BIOS&#xff08;Bas…

澳洲猫罐头真实水平如何?我家亲自喂养过的优质猫罐头推荐给大家

当我们选择猫罐头时&#xff0c;要关注它的营养配方是否完整均衡、原料是否新鲜优质以及生产工艺是否科学可靠。只有满足这三个条件的猫罐头&#xff0c;才能称得上是高品质的。 猫罐头要营养均衡&#xff0c;好的配方不能少&#xff1b;猫罐头成品要优质&#xff0c;原材料要…

文心一言 VS 讯飞星火 VS chatgpt (139)-- 算法导论11.4 3题

三、用go语言&#xff0c;考虑一个采用均匀散列的开放寻址散列表。当装载因子为 3/4 和 7/8 时&#xff0c;试分别给出一次不成功查找和一次成功查找的探查期望数上界。 文心一言&#xff1a; 在开放寻址法中&#xff0c;当散列表的装载因子超过其阈值时&#xff0c;会触发重…

文件加密软件哪个好丨2023年最值得收藏的6款文件加密软件

文件加密软件哪个好&#xff1f; 在这个安全事件频发的时代&#xff0c;信息安全、文件安全已成为很多人关注的话题。不管是电脑还是手机&#xff0c;都需要重视文件加密这个话题。 那今天就推荐6款最值得收藏的文件加密软件&#xff0c;并分析其中的优缺点。 一、电脑加密软…

《洛谷深入浅出基础篇》 图的基本应用

什么是图&#xff1f; 我们在生活中学习中能看见很多图&#xff0c;地图&#xff0c;路线图&#xff0c;思维导图等等&#xff0c;它们都有一个特点&#xff0c; 你从中任找一个点&#xff0c;你可以找到&#xff0c;从这个点出发&#xff0c;能够到达什么地方&#xff0c;也…

哪些软件可以监控电脑(保姆级教程!值得收藏!)

今天了解到了一个软件&#xff0c;真的把我吓到了。 我才知道原来我上班时摸鱼时多么愚蠢的一件事情。原来老板可以通过一些软件轻而易举的知道你用电脑做的所有事情&#xff0c;怪不得我每次摸鱼时老板看我的眼神都不对…… 安装好域之盾软件以后&#xff0c;打开就能监控你使…

2023年通信安全员ABC证证模拟考试题库及通信安全员ABC证理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年通信安全员ABC证证模拟考试题库及通信安全员ABC证理论考试试题是由安全生产模拟考试一点通提供&#xff0c;通信安全员ABC证证模拟考试题库是根据通信安全员ABC证最新版教材&#xff0c;通信安全员ABC证大纲整理…

使用Dockerfile构建hexo博客镜像,并部署

基于centos7.9父镜像构建hexo:1.0镜像&#xff1a; cat << eof > Dockerfile # 根镜像 FROM centos:7.9.2009 MAINTAINER qv123<qv1095322098163.com> # 设置工作目录 WORKDIR /usr/src/app # 暴露端口号 EXPOSE 4000 # 作者注释 MAINTAINER qv123<qv1095322…

用对了吗?正确打开文件传输助手的方式

在这个高速发展的信息时代&#xff0c;我们每天都会面临一个重要的问题&#xff1a;如何在手机和电脑之间快速、高效地传输文件&#xff1f; 有时候&#xff0c;我们需要把工作中的一份报告从电脑传到手机&#xff0c;以便在路上查看&#xff1b;有时候&#xff0c;我们又想把手…