0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Nacos、OpenFeign、Ribbon组件协调工作的原理

jf_ro2CN3Fa 来源:三友的java日记 2023-05-22 10:46 次阅读

Nacos

如何进行服务自动注册?

Ribbon

OpenFeign

总结

前几天有个大兄弟问了我一个问题,注册中心要集成SpringCloud,想实现SpringCloud的负载均衡,需要实现哪些接口和规范。

既然这个兄弟问到我了,而我又刚好知道,这不得好好写一篇文章来回答这个问题,虽然在后面的聊天中我已经回答过了。

接下来本文就来探究一下Nacos、OpenFeign、Ribbon、loadbalancer等组件协调工作的原理,知道这些原理之后,就知道应该需要是实现哪些接口了。

Nacos

先从Nacos讲起。

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

5c6baf8c-f7ce-11ed-90ce-dac502259ad0.png

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

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

5c73dab8-f7ce-11ed-90ce-dac502259ad0.png

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

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

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

引入依赖


com.alibaba.nacos
nacos-client
1.4.4

示例代码

Propertiesproperties=newProperties();
properties.setProperty("serverAddr","localhost");
properties.setProperty("namespace","8848");

NamingServicenaming=NamingFactory.createNamingService(properties);

//服务注册,注册一个order服务,order服务的ip是192.168.2.100,端口8080
naming.registerInstance("order","192.168.2.100",8080);

//服务发现,获取所有的order服务实例
ListinstanceList=naming.selectInstances("order",true);

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

5c866fb6-f7ce-11ed-90ce-dac502259ad0.png

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

如何进行服务自动注册?

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

服务自动注册三板斧

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

服务实例数据封装--Registration

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

5c90b9b2-f7ce-11ed-90ce-dac502259ad0.pngRegistration 5c9ae644-f7ce-11ed-90ce-dac502259ad0.pngServiceInstance

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

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

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

5ca5fb7e-f7ce-11ed-90ce-dac502259ad0.pngNacosRegistration

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

服务注册--ServiceRegistry

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

5cb94a76-f7ce-11ed-90ce-dac502259ad0.pngServiceRegistry

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

Nacos也实现了这个接口。

5cc43562-f7ce-11ed-90ce-dac502259ad0.pngNacosServiceRegistry

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

5cce874c-f7ce-11ed-90ce-dac502259ad0.png

服务自动注册--AutoServiceRegistration

5ce63bbc-f7ce-11ed-90ce-dac502259ad0.pngAutoServiceRegistration

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

AutoServiceRegistration有个抽象实现AbstractAutoServiceRegistration

5cf02f6e-f7ce-11ed-90ce-dac502259ad0.pngAbstractAutoServiceRegistration是个抽象类

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

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

5cfea53a-f7ce-11ed-90ce-dac502259ad0.png

ServletWebServerInitializedEvent继承自WebServerInitializedEvent。

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

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

5d09a0fc-f7ce-11ed-90ce-dac502259ad0.png

Nacos自然而然也继承了AbstractAutoServiceRegistration

5d13ef80-f7ce-11ed-90ce-dac502259ad0.pngNacosAutoServiceRegistration

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

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

5d22304a-f7ce-11ed-90ce-dac502259ad0.png

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

5d2e6234-f7ce-11ed-90ce-dac502259ad0.png

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

视频教程:https://doc.iocoder.cn/video/

Ribbon

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

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

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

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

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

5d398a6a-f7ce-11ed-90ce-dac502259ad0.pngServerList

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

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

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

5d439c62-f7ce-11ed-90ce-dac502259ad0.pngNacosServerList

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

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

5d4cc2ec-f7ce-11ed-90ce-dac502259ad0.png

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

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

5d59e2ba-f7ce-11ed-90ce-dac502259ad0.jpg

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

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

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

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

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

5d62b444-f7ce-11ed-90ce-dac502259ad0.pngDiscoveryClient

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

5d6c5b48-f7ce-11ed-90ce-dac502259ad0.png

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


org.springframework.cloud
spring-cloud-starter-loadbalancer
2.2.5.RELEASE

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

5d7b6962-f7ce-11ed-90ce-dac502259ad0.png

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

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/yudao-cloud

视频教程:https://doc.iocoder.cn/video/

OpenFeign

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

5d859a36-f7ce-11ed-90ce-dac502259ad0.png

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

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

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

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

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

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

5d8df4d8-f7ce-11ed-90ce-dac502259ad0.png

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

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

5d94759c-f7ce-11ed-90ce-dac502259ad0.pngreconstructURIWithServer

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

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

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

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

5da1c3dc-f7ce-11ed-90ce-dac502259ad0.pngloadbalancer组件重构url代码

总结

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

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

5dacdd58-f7ce-11ed-90ce-dac502259ad0.png

审核编辑:彭静

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    7656

    浏览量

    148599
  • 服务端
    +关注

    关注

    0

    文章

    62

    浏览量

    6874
  • nacos
    +关注

    关注

    0

    文章

    10

    浏览量

    165

原文标题:终于搞懂了 Nacos、OpenFeign、Ribbon 等组件协调工作的原理,太强了!

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Nacos是什么?Nacos配置管理技巧你知道吗

    Nacos 是阿里巴巴今年7月份开源的项目,如其名, Naming Configuration Service ,专注于服务发现和配置管理领域。本系列文章,将从 5W1H(What、Where
    的头像 发表于 10-29 08:53 1.4w次阅读

    Nacos的概念和功能

    1、Nacos简介 Nacos的概念和功能 Nacos是一个面向微服务架构的动态服务发现、配置管理和服务治理平台,它能够帮助开发人员和运维人员实现服务注册、配置管理、DNS和负载均衡等功能。 下面
    的头像 发表于 09-25 11:02 876次阅读

    支持Dubbo生态发展,阿里巴巴启动新的开源项目 Nacos

    摘要: 上周六的Aliware技术行上海站Dubbo开发者沙龙上,阿里巴巴高级技术专家郭平(坤宇)宣布了阿里巴巴的一个新开源计划,阿里巴巴计划在7月份开启一个名叫Nacos的新开源项目, 在活动演讲
    发表于 07-05 17:35

    如何为常规Python App包含Qtitan组件

    Developer Machines公司主要为开源UI开发框架QT提供商业组件,其中拥有Chart、DataGrid、Ribbon等控件。本文主要介绍如何为常规Python App包含Qtitan
    发表于 12-17 07:45

    构建ARM64版本nacos docker镜像

    在适配过程中有大量合作伙伴用到nacos且采用容器化部署,dockerhub未提供官方镜像,因此需要在鲲鹏服务器自定义构建。构建前提:Docker已部署构建步骤:1、下载包含构建所需的脚本下载完成
    发表于 06-16 14:29

    微服务配置中心实战:Spring + MyBatis + Druid + Nacos

    在 结合场景谈服务发现和配置 中我们讲述了 Nacos 配置中心的三个典型的应用场景,包括如何在 Spring Boot 中使用 Nacos 配置中心将数据库连接信息管控起来,而在“原生
    发表于 12-29 17:09 934次阅读
    微服务配置中心实战:Spring + MyBatis + Druid + <b class='flag-5'>Nacos</b>

    ApiBoot Logging使用Spring Cloud Openfeign透传链路信息

    ApiBoot Logging可以无缝整合SpringCloud来采集请求日志,目前支持RestTemplate、Openfeign两种方式,我们本章来讲解下在使用Openfeign...
    的头像 发表于 12-10 22:05 370次阅读

    Nacos服务地址动态感知原理

    Nacos Server:Nacos服务提供者,里面包含的Open API是功能访问入口,Conig Service、Naming Service 是Nacos提供的配置服务、命名服务模块。
    的头像 发表于 09-26 10:40 1479次阅读

    Nacos为什么这么强?Nacos注册中心的底层原理,从服务注册到服务发现

    来源:码猿技术专栏 1. Nacos介绍 2. Nacos注册中心实现原理分析 2.1 Nacos架构图 2.2 注册中心的原理 3. Nacos源码分析 3.1
    的头像 发表于 10-08 16:46 1.1w次阅读

    华为云CSE 关键特性,支持托管Nacos注册配置中心

    华为云CSE关键特性,支持托管Nacos注册配置中心 什么是Nacos Nacos是 Dynamic Naming and Configuration Service的首字母简称,相较之下,它更易
    的头像 发表于 12-29 16:23 782次阅读
    华为云CSE 关键特性,支持托管<b class='flag-5'>Nacos</b>注册配置中心

    华为云微服务引擎0停机迁移Nacos?它是这样做的

    后使用CSE,但是目前想使用Nacos过渡情况。 • 倾向使用Nacos作为配置中心使用,其它使用华为云的其它组件,如CCE、中间件等。
    的头像 发表于 12-29 20:01 539次阅读

    基于Nacos的简单动态化线程池实现

    本文以Nacos作为服务配置中心,以修改线程池核心线程数、最大线程数为例,实现一个简单的动态化线程池。
    发表于 01-06 14:14 639次阅读

    Nacos测试环境中cpu飙高的原因和解决方案

    出问题的项目是 需要连接各个不同nacos 和不同的 namespace 进行对应操作的 一个项目,对nacos的操作都是httpClient 调用的api接口,httpClient方法 没有问题,不用质疑这个
    发表于 05-12 11:20 2436次阅读
    <b class='flag-5'>Nacos</b>测试环境中cpu飙高的原因和解决方案

    Nacos实现原理:SpringCloud集成Nacos的实现过程

    Nacos服务提供者,里面包含的Open API是功能访问入口,Conig Service、Naming Service 是Nacos提供的配置服务、命名服务模块。Consitency
    发表于 10-09 16:08 143次阅读
    <b class='flag-5'>Nacos</b>实现原理:SpringCloud集成<b class='flag-5'>Nacos</b>的实现过程

    springcloud alibaba 五大组件

    与发现组件Nacos): Nacos是一个用于实现服务注册和发现的组件。它提供了一个简单易用的界面来注册、发现和管理服务实例,同时还支持动态配置、服务路由和流量管理等功能。
    的头像 发表于 12-03 16:30 9711次阅读