大家好,我是不才陈某~

前几天有个大兄弟问了我一个问题,注册核心要集成SpringCloud,想实现SpringCloud的负载平衡,须要实现哪些接口和标准。

Java指南:www.java-family.cn

既然这个兄弟问到我了,而我又刚好晓得,这不得好好写一篇文章来答复这个问题,尽管在前面的聊天中我曾经答复过了。

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

再多说一句,本文并没有具体地深刻分析各个组件的源码,如果有感兴趣的兄弟能够从公众号后盾菜单栏中的文章分类中查看我之前写的对于Nacos、OpenFeign、Ribbon源码分析的文章。

Nacos

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

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

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

  • 服务端须要独自部署,用来保留服务实例数据的
  • 客户端就是用来跟服务端通信的SDK,反对不同语言
Java指南:www.java-family.cn

当须要向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,端口8080naming.registerInstance("order", "192.168.2.100", 8080);//服务发现,获取所有的order服务实例List<Instance> instanceList = naming.selectInstances("order", true);

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

这个汇合在注册核心界中有个嘹亮的名字,服务注册表

如何进行服务主动注册?

用过SpringCloud的小伙伴必定晓得,在我的项目启动的时候服务可能主动注册到服务注册核心,并不需要手动写下面那段代码,那么服务主动注册是如何实现的呢?

服务主动注册三板斧

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

服务实例数据封装--Registration

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

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

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

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

这样以后服务须要被注册到注册核心的信息就封装好了。

服务注册--ServiceRegistry

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

这个接口的作用就是把下面封装的以后服务的数据Registration注册通过register办法注册到注册核心中。

Nacos也实现了这个接口。

并且外围的注册办法的实现代码跟后面的demo简直一样

服务主动注册--AutoServiceRegistration

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

AutoServiceRegistration有个形象实现AbstractAutoServiceRegistration

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

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

ServletWebServerInitializedEvent继承自WebServerInitializedEvent。

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

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

Nacos自然而然也继承了AbstractAutoServiceRegistration

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

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

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

Ribbon

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

咱们都晓得,Ribbon是负载平衡组件,他的作用就是从泛滥的服务实例中依据肯定的算法抉择一个服务实例。

然而有个疑难,服务实例的数据都在注册核心,Ribbon是怎么晓得的呢???

答案其实很简略,那就是须要注册核心去被动适配Ribbon,只有注册核心去适配了Ribbon,那么Ribbon自然而然就晓得服务实例的数据了。

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

接口中提供了两个办法,这两个办法在泛滥的实现中理论是一样的,并没有区别。

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

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

这样,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就可能获取到服务实例,当然也是须要不同注册核心的适配。

随着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和端口,代码如下

  • 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申请。

总结

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

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

最初再小小地说一句,Nacos、OpenFeign、Ribbon源码分析的文章,能够从公众号后盾菜单栏中的文章分类中查看。

最初说一句(别白嫖,求关注)

陈某每一篇文章都是精心输入,如果这篇文章对你有所帮忙,或者有所启发的话,帮忙点赞在看转发珍藏,你的反对就是我坚持下去的最大能源!

另外陈某的常识星球开明了,公众号回复关键词:常识星球 获取限量20元优惠券退出只需109元,星球回馈的价值微小,目前更新了Spring全家桶实战系列亿级数据分库分表实战DDD微服务实战专栏我要进大厂、Spring,Mybatis等框架源码、架构实战22讲、精尽RocketMQ等....每减少一个专栏价格将上涨20元

关注公众号:【码猿技术专栏】,公众号内有超赞的粉丝福利,回复:加群,能够退出技术探讨群,和大家一起探讨技术,吹牛逼!