「分享学习」 微服务实战项目SpringCloudalibaba+Vue开发仿社交小程序

学习视频预览地址:

download: https://resource.youziit.com/2023/07/29/%e5%be%ae%e6%9c%8d%e5%8a%a1%e5%ae%9e%e6%88%98%e9%a1%b9%e7%9b%aespringcloudalibabavue%e5%bc%80%e5%8f%91%e4%bb%bf%e7%a4%be%e4%ba%a4%e5%b0%8f%e7%a8%8b%e5%ba%8f-%e5%ae%98%e6%96%b9%e5%90%8c%e6%ad%a5/

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

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

Nacos

先从Nacos讲起。

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

[图片上传失败...(image-69d09b-1700208323548)]

这一段话说的直白点就是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服务端的时候,在服务端内部会有一个集合去存储服务的信息

[图片上传失败...(image-b8fce-1700208323547)]

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

如何进行服务自动注册?

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

服务自动注册三板斧

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

服务实例数据封装--Registration

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

[图片上传失败...(image-bb39ed-1700208323547)] Registration[图片上传失败...(image-a2bcdf-1700208323547)] ServiceInstance

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

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

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

[图片上传失败...(image-daeb6f-1700208323547)] NacosRegistration

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

服务注册--ServiceRegistry

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

[图片上传失败...(image-aa1ced-1700208323547)] ServiceRegistry

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

Nacos也实现了这个接口。

[图片上传失败...(image-f05b2e-1700208323547)] NacosServiceRegistry

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

[图片上传失败...(image-c4c3a7-1700208323547)]

服务自动注册--AutoServiceRegistration

[图片上传失败...(image-70a09e-1700208323547)] AutoServiceRegistration

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

AutoServiceRegistration有个抽象实现AbstractAutoServiceRegistration

[图片上传失败...(image-79cbb3-1700208323547)] AbstractAutoServiceRegistration是个抽象类

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

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

[图片上传失败...(image-23f804-1700208323547)]

ServletWebServerInitializedEvent继承自WebServerInitializedEvent。

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

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

[图片上传失败...(image-e2f6ed-1700208323547)]

Nacos自然而然也继承了AbstractAutoServiceRegistration

NacosAutoServiceRegistration

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

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

[图片上传失败...(image-df92ed-1700208323547)]

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

Ribbon

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

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

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

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

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

[图片上传失败...(image-9f94bd-1700208323547)] ServerList

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

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

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

[图片上传失败...(image-a3fb16-1700208323547)] NacosServerList

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

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

[图片上传失败...(image-911d40-1700208323547)]

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

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

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

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

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

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

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

[图片上传失败...(image-59d728-1700208323547)] DiscoveryClient

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

[图片上传失败...(image-9cdd89-1700208323547)]

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

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

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

[图片上传失败...(image-8a3d46-1700208323547)]

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

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

OpenFeign

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

[图片上传失败...(image-f4a908-1700208323547)]

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

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

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

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

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

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

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

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

[图片上传失败...(image-72a68a-1700208323547)] 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请求。

[图片上传失败...(image-d2ccf3-1700208323547)] loadbalancer组件重构url代码

总结

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

[图片上传失败...(image-e3568f-1700208323548)]

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容