Nacos、OpenFeign、Ribbon、loadbalancer组件工作的原理

Nacos、OpenFeign、Ribbon、loadbalancer组件工作的原理

Nacos是什么,官网中有这么一段话

图片

这一段话说的直白点就是Nacos是一个注册中心和配置中心!

在Nacos中有客户端和服务端的这个概念

图片

  • 服务端需要单独部署,用来保存服务实例数据的

  • 客户端就是用来跟服务端通信的SDK,支持不同语言

当需要向Nacos服务端注册或者获取服务实例数据的时候,只需要通过Nacos提供的客户端SDK就可以了,就像下面这样:

引入依赖

<dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>1.4.4</version>
</dependency>

示例代码

Properties properties = new Properties();
properties.setProperty("serverAddr", "localhost");
properties.setProperty("namespace", "8848");NamingService naming = NamingFactory.createNamingService(properties);//服务注册,注册一个order服务,order服务的ip是192.168.2.100,端口8080
naming.registerInstance("order", "192.168.2.100", 8080);//服务发现,获取所有的order服务实例
List<Instance> instanceList = naming.selectInstances("order", true);

当服务注册到Nacos服务端的时候,在服务端内部会有一个集合去存储服务的信息

图片

这个集合在注册中心界中有个响亮的名字,服务注册表

如何进行服务自动注册?

用过SpringCloud的小伙伴肯定知道,在项目启动的时候服务能够自动注册到服务注册中心,并不需要手动写上面那段代码,那么服务自动注册是如何实现的呢?

服务自动注册三板斧

SpringCloud本身提供了一套服务自动注册的机制,或者说是约束,其实就是三个接口,只要注册中心实现这些接口,就能够在服务启动时自动注册到注册中心,而这三个接口我称为服务自动注册三板斧。

服务实例数据封装--Registration

Registration是SpringCloud提供的一个接口,继承了ServiceInstance接口

图片

Registration

图片

ServiceInstance

从ServiceInstance的接口定义可以看出,这是一个服务实例数据的封装,比如这个服务的ip是多少,端口号是多少。

所以Registration就是当前服务实例数据封装,封装了当前服务的所在的机器ip和端口号等信息。

Nacos既然要整合SpringCloud,自然而然也实现了这个接口

图片

NacosRegistration

这样当前服务需要被注册到注册中心的信息就封装好了。

服务注册--ServiceRegistry

ServiceRegistry也是个接口,泛型就是上面提到的服务实例数据封装的接口

图片

ServiceRegistry

这个接口的作用就是把上面封装的当前服务的数据Registration注册通过register方法注册到注册中心中。

Nacos也实现了这个接口。

图片

NacosServiceRegistry

并且核心的注册方法的实现代码跟前面的demo几乎一样

图片

服务自动注册--AutoServiceRegistration

图片

AutoServiceRegistration

AutoServiceRegistration是一个标记接口,所以本身没有实际的意义,仅仅代表了自动注册的意思。

AutoServiceRegistration有个抽象实现AbstractAutoServiceRegistration

图片

AbstractAutoServiceRegistration是个抽象类

AbstractAutoServiceRegistration实现了ApplicationListener,监听了WebServerInitializedEvent事件。

WebServerInitializedEvent这个事件是SpringBoot在项目启动时,当诸如tomcat这类Web服务启动之后就会发布,注意,只有在Web环境才会发布这个事件。

图片

ServletWebServerInitializedEvent继承自WebServerInitializedEvent。

所以一旦当SpringBoot项目启动,tomcat等web服务器启动成功之后,就会触发AbstractAutoServiceRegistration监听器的执行。

最终就会调用ServiceRegistry注册Registration,实现服务自动注册

图片

Nacos自然而然也继承了AbstractAutoServiceRegistration

图片

NacosAutoServiceRegistration

对于Nacos而言,就将当前的服务注册的ip和端口等信息,就注册到了Nacos服务注册中心。

所以整个注册流程就可以用这么一张图概括

图片

当然,不仅仅是Nacos是这么实现的,常见的比如Eureka、Zookeeper等注册中心在整合SpringCloud都是实现上面的三板斧。

图片

Ribbon

讲完了SpringCloud环境底下是如何自动注册服务到注册中心的,下面来讲一讲Ribbon。

我们都知道,Ribbon是负载均衡组件,他的作用就是从众多的服务实例中根据一定的算法选择一个服务实例。

但是有个疑问,服务实例的数据都在注册中心,Ribbon是怎么知道的呢???

答案其实很简单,那就是需要注册中心去主动适配Ribbon,只要注册中心去适配了Ribbon,那么Ribbon自然而然就知道服务实例的数据了。

Ribbon提供了一个获取服务实例的接口,叫ServerList

图片

ServerList

接口中提供了两个方法,这两个方法在众多的实现中实际是一样的,并没有区别。

当Ribbon通过ServerList获取到服务实例数据之后,会基于这些数据来做负载均衡的。

Nacos自然而然也实现了ServerList接口,为Ribbon提供Nacos注册中心中的服务数据。

图片

NacosServerList

这样,Ribbon就能获取到了Nacos服务注册中心的数据。

同样地,除了Nacos之外,Eureka、Zookeeper等注册中心也都实现了这个接口。

图片

到这,其实就明白了Ribbon是如何知道注册中心的数据了,需要注册中心来适配。

在这里插个个人的看法,其实我觉得Ribbon在适配SpringCloud时对获取服务实例这块支持封装的不太好。

因为SpringCloud本身就是一套约束、规范,只要遵守这套规范,那么就可以实现各个组件的替换,这就是为什么换个注册中心只需要换个依赖,改个配置文件就行。

而Ribbon本身是一个具体的负载均衡组件,注册中心要想整合SpringCloud,还得需要单独去适配Ribbon,有点违背了SpringCloud约束的意义。

就类似mybatis一样,mybatis依靠jdbc,但是mybatis根本不关心哪个数据库实现的jdbc。

真正好的做法是Ribbon去适配SpringCloud时,用SpringCloud提供的api去获取服务实例,这样不同的注册中心只需要适配这个api,无需单独适配Ribbon了。

而SpringCloud实际上是提供了这么一个获取服务实例的api,DiscoveryClient

图片

DiscoveryClient

通过DiscoveryClient就能够获取到服务实例,当然也是需要不同注册中心的适配。

图片

随着Ribbon等组件停止维护之后,SpringCloud官方自己也搞了一个负载均衡组件loadbalancer,用来平替Ribbon。

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId><version>2.2.5.RELEASE</version>
</dependency>

这个组件底层在获取服务实例的时候,就是使用的DiscoveryClient。

图片

所以对于loadbalancer这个负载均衡组价来说,注册中心只需要实现DiscoveryClient之后就自然而然适配了loadbalancer

OpenFeign

OpenFeign是一个rpc框架,当我们需要调用远程服务的时候,只需要声明个接口就可以远程调用了,就像下面这样

图片

听上去很神奇,其实本质上就是后面会为接口创建一个动态代理对象,解析类上,方法上的注解。

当调用方法的时候,会根据方法上面的参数拼接一个http请求地址,这个地址的格式是这样的http://服务名/接口路径

比如,上面的例子,当调用saveOrder方法的时候,按照这种规律拼出的地址就是这样的 http://order/order,第一个order是服务名,第二个order是PostMapping注解上面的。

但是由于只知道需要调用服务的服务名,不知道服务的ip和端口,还是无法调用远程服务,这咋办呢?

这时就轮到Ribbon登场了,因为Ribbon这个大兄弟知道服务实例的数据。

于是乎,OpenFeign就对Ribbon说,兄弟,你不是可以从注册中心获取到order服务所有服务实例数据么,帮我从这些服务实例数据中找一个给我。

图片

于是Ribbon就会从注册中心获取到的服务实例中根据负载均衡策略选择一个服务实例返回给OpenFeign。

OpenFeign拿到了服务实例,此时就获取到了服务所在的ip和端口,接下来就会重新构建请求路径,将路径中的服务名替换成ip和端口,代码如下

图片

reconstructURIWithServer

  • Server就是服务实例信息的封装

  • orignal就是原始的url,就是上面提到的,http://order/order

假设获取到的orde服务所在的ip和端口分别是192.168.2.1008080,最终重构后的路径就是http://192.168.2.100:8080/order,之后OpenFeign就可以发送http请求了。

至于前面提到的loadbalancer,其实也是一样的,他也会根据负载均衡算法,从DiscoveryClient获取到的服务实例中选择一个服务实例给OpenFeign,后面也会根据服务实例重构url,再发送http请求。

图片

loadbalancer组件重构url代码

总结

到这,就把Nacos、OpenFeign、Ribbon、loadbalancer等组件协调工作的原理讲完了,其实就是各个组件会预留一些扩展接口,这也是很多开源框架都会干的事,当第三方框架去适配的,只要实现这些接口就可以了。

最后画一张图来总结一下上述组价的工作的原理。

图片

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

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

相关文章

LeGO-LOAM 安装以及运行

一、源码地址&#xff1a; GitHub - RobustFieldAutonomyLab/LeGO-LOAM: LeGO-LOAM: Lightweight and Ground-Optimized Lidar Odometry and Mapping on Variable TerrainLeGO-LOAM: Lightweight and Ground-Optimized Lidar Odometry and Mapping on Variable Terrain - GitH…

【RockChip | RV1126】学习与开发

【RockChip | RV1126】学习与开发 文章目录 【RockChip | RV1126】学习与开发1. 资料 1. 资料 您好&#xff0c;这是关于A191型RV1126的资料包&#xff0c;请您及时接收哦~链接: https://pan.baidu.com/s/1FXWVxa27Q78nI78d2QKlBQ?pwdj7mk 提取码: j7mk 若您在开发过程中遇到技…

程序员必备的面试技巧

程序员必备的面试技巧 程序员必备的面试技巧&#xff0c;就像是编写一段完美的代码一样重要。在面试战场上&#xff0c;我们需要像忍者一样灵活&#xff0c;像侦探一样聪明&#xff0c;还要像无敌铁金刚一样坚定。只有掌握了这些技巧&#xff0c;我们才能在面试的舞台上闪耀光…

Hive 的 安装与部署

目录 1 安装 MySql2 安装 Hive3 Hive 元数据配置到 MySql4 启动 Hive Hive 官网 1 安装 MySql 为什么需要安装 MySql? 原因在于Hive 默认使用的元数据库为 derby&#xff0c;开启 Hive 之后就会占用元数据库&#xff0c;且不与其他客户端共享数据&#xff0c;如果想多窗口操作…

C语言光速入门笔记

C语言是一门面向过程的编译型语言&#xff0c;它的运行速度极快&#xff0c;仅次于汇编语言。C语言是计算机产业的核心语言&#xff0c;操作系统、硬件驱动、关键组件、数据库等都离不开C语言&#xff1b;不学习C语言&#xff0c;就不能了解计算机底层。 目录 C语言介绍C语言特…

【Linux Shell】12. 文件包含

和其他语言一样&#xff0c;Shell 也可以包含外部脚本&#xff0c;这样可以很方便的封装一些公用的代码作为一个独立的文件。可以理解为在第2个文件中包含第1个文件&#xff0c;执行第1个文件的代码。 被包含的文件 不需要可执行权限 。Shell 文件包含的语法格式如下&#xff1…

mysql基础-表数据操作之查

目录 1.别名 2. 单表查询 2.1 模糊查询 - like 2.2 limit 2.3 order by 2.4 group by 2.5 in 2.6 between and 2.6 is null 2.7 not 2.8 运算符 3. 联表查询 全连接 左连接 右连接 本次分享一下数据的DQL语言。 1.别名 首先分享一下别名的知识。我们在查询的时…

05 Ciso模拟器连接腾讯云物联网开发平台

Ciso声明&#xff1a;本篇文章基于使用腾讯云物联网平台连接自定义esp8266物联网设备(腾讯连连控制开关实现) - CSDN App改编 一、总体概览 功能描述&#xff1a; 使用腾讯连连小程序进行控制&#xff0c; Alarm&#xff08;警铃&#xff09;&#xff1a;开的时候&#xff…

【Spring实战】20 Spring Data REST+JPA构建基础的RESTful API

文章目录 1. 基础概念1&#xff09;Spring Data REST2&#xff09;JPA&#xff08;Java Persistence API&#xff09; 2. 添加依赖3. 创建JPA实体4. 创建JPA Repository5. 启用Spring Data REST6. 启动服务7. 测试8. 总结 Spring Data REST 是 Spring Framework 生态系统中的一…

OpenSSL——升级

OpenSSL&#xff08;Open Secure Sockets Layer&#xff09;是一个开源的软件库&#xff0c;提供了SSL和TLS协议的实现&#xff0c;用于加密通信。它广泛用于安全连接&#xff0c;例如在网站上通过HTTPS协议进行安全的数据传输. 但是从openssl申请道德证书是不安全的。对于网站…

【算法每日一练]-动态规划(保姆级教程 篇14) #三倍经验 #散步 #异或和 #抽奖概率

目录 今日知识点&#xff1a; 金字塔的正反dp两种方案&#xff0c;转移方程取决于dp的具体含义 取模实现循环走m步回到原点的方案 在统计上升子序列的时候使用最小结尾元素进行标记&#xff0c;一举两得 将亏本的概率转换各种情况的方案&#xff0c;然后统计亏本的情况的方…

已解决 | Go Error: redeclared as imported package name 问题

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…

RH850P1X芯片学习笔记-A/D Converter (ADCF)

文章目录 Features of RH850/P1x-C ADCFNumber of UnitsRegister Base AddressClock SupplyInterrupts and DMAHardware ResetExternal Input/Output SignalsVirtual Channel OverviewFunctional OverviewBlock DiagramPhysical Channels, Virtual Channels and Scan Groups Re…

数据结构和算法-数据结构的基本概念和三要素和数据类型和抽象数据类型

文章目录 总览数据结构的基本概念总览数据早期和现代的计算机处理的数据数据元素-描述一个个体数据对象-一类数据元素什么是数据结构小结 数据结构的三要素总览逻辑结构-集合结构逻辑结构-线性结构逻辑结构-树形结构逻辑结构-图形结构逻辑结构-小结数据的运算物理结构&#xff…

7个Pandas绘图函数助力数据可视化

大家好&#xff0c;在使用Pandas分析数据时&#xff0c;会使用Pandas函数来过滤和转换列&#xff0c;连接多个数据帧中的数据等操作。但是&#xff0c;生成图表将数据在数据帧中可视化&#xff0c;通常比仅仅查看数字更有帮助。 Pandas具有几个绘图函数&#xff0c;可以使用它…

复试 || 就业day05(2024.01.08)项目一

文章目录 前言代码模拟梯度下降构建函数与导函数函数的可视化求这个方程的最小值&#xff08;直接求导&#xff09;求方程最小值&#xff08;不令方程导为0&#xff09;【梯度下降】eta0.1eta 0.2eta 50eta 0.01画出eta0.1时的梯度下降x的变化过程 总结 前言 &#x1f4ab;你…

Python将Labelme文件的真实框和预测框绘制到图片上

Python将Labelme文件的真实框和预测框绘制到图片上 前言前提条件相关介绍实验环境Python将Labelme文件的标注信息绘制到图片上代码实现输出结果 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评改正。更多精彩内容&#xff0c;可点击进入Python日常小操作专…

qt信号和槽

Qt是一个跨平台的C图形用户界面应用框架 91年奇趣科技开发 pro工程文件介绍 .pro就是工程文件(project)&#xff0c;它是qmake自动生成的用于生产makefile的配置文件 QT core gui //Qt包含的模块greaterThan(QT_MAJOR_VERSION, 4): QT widgets //大于4版本包含…

2024.1.2 Redis 数据类型 Stream、Geospatial、HyperLogLog、Bitmaps、Bitfields 简介

目录 引言 Stream 类型 Geospatial 类型 HyperLogLog 类型 Bitmaps 类型 Bitfields 类型 引言 Redis 最关键&#xff08;应用广泛、频繁使用&#xff09;的五个数据类型 StringListHashSetZSet 下文介绍的数据类型一般适合在特定的场景中使用&#xff01; Stream 类型 St…

强化学习的数学原理学习笔记 - 基于模型(Model-based)

文章目录 概览&#xff1a;RL方法分类基于模型&#xff08;Model-Based&#xff09;值迭代&#xff08;Value Iteration&#xff09;&#x1f7e6;策略迭代&#xff08;Policy Iteration&#xff09;&#x1f7e1;截断策略迭代&#xff08;Truncated Policy Iteration&#xff…