首先从个人发展角度,如果一个新时期码农能清楚的理解RPC框架所具备的要素,节制RPC框架中涉及的做事注册创造、负载均衡、序列化协议、RPC通信协议、Socket通信、异步调用、熔断降级等技能,可以全方位的提升基本本色。
其次,目前市情上也有非常多精良的框架,GitHub上也有干系源码,但好记性不如烂笔头,只有自己真正理解并且动手去考试测验写一个RPC框架,才是我们去节制这门技能的最优路径。
研究一个观点或者框架,带着三个W去考虑,可能会对他有更加深刻的理解:

1)What,什么是RPC框架,RPC是 Remote Procedure Call 的简称,远程过程调用,那么什么叫远程过程调用呢,你可以理解为我们调用外部(远程)做事就像调用自己本地方法一样。
2)Where,RPC框架用在什么地方,在分布式系统和微做事盛行的本日,各业务系统会被独立拆分出来成为一个个独立的web运用,运用之间的交互和数据传输就成了必不可少的一环,RPC便是为了实现独立做事之间远程交互的框架。
3)Why,为什么须要一个RPC框架,做事之间的调用须要各种场景和成分的考虑,内部事理非常繁芜和繁琐,同时在集议论形下,做事的负载均衡,熔断,限流等都是须要去考虑的,这时候就须要一个集做事注册创造、负载均衡、序列化协议、RPC通信协议、Socket通信、异步调用、熔断降级等技能为一体的技能去完成这些公共功能,RPC框架便是在这种情形下应运而生。
目前比较主流的RPC框架包括谷歌开源的GRPC、阿里巴巴的Dubbo、Netflix 的SpringCloud等。
二、RPC框架基本组成RPC框架须要的最基本的三个要素:
ServiceProvider: 做事供应方,供应干系做事接口。ServiceConsumer: 做事消费方,消费做事供应方的接口。Registry: 注册中央,用于进行做事的注册、创造、管理、高可用。基于三个最基本要素,还会延伸出包括负载均衡器、熔断降级器、通信协议组件、序列化协议等等组件。
一个最大略的RPC调用模型图如下所示:
下面做一些名词的先容和解释:
2.1 注册中央注册中央是RPC框架中的管理者和折衷者角色,虽然在远程过程调用中做事消费者会不经由注册中央,会直接向做事供应者发送要求,但是随着我们的做事方越来越多,每个做事的实例也不断变革的,且每个做事的地址,端口等信息是须要关照到消费方的,以是我们须要一个类似“管家”的角色,来卖力管理做事注册和创造的事情,这个“管家”我们称之为注册中央。
一个合格的注册中央须要具备包括缓存和持久化做事供应方数据,动态更新做事供应者信息,动态监听做事供应方节点变革,推送节点变革到消费方,查询做事供应方数据等功能。
目前市情上比较盛行的注册中央有:Zookper、 Nacos、Consul、Eurake等,针对付上面功能的实现办法也有所不同,以下是注册中央的比拟:
Zookeeper
Nacos
Consul
Eurake
同等性协议
CP
CP + AP
CP
AP
雪崩保护
无
有
无
有
多数据中央
不支持
支持
支持
支持
自动注销实例
支持
支持
支持
支持
2.2 做事供应方(RPC做事端)其须要对外供应做事接口,一个做事方须要包括启动连接注册中央,注册干系信息到注册中央,供应做事下线和更新机制,掩护做事名和做事的映射,序列化和反序列化,启动通信等
目前做事供应方有两种做事供应维度,基于接口的做事供应和基于做事的做事供应,Dubbo3.0 之前是基于接口维度做的做事注册,Dubbo3.0之后逐渐向做事维度的做事注册创造靠拢,SpringCloud是基于做事来进行注册创造的,在云原生和容器化越来越火的本日,基于做事可以更好的适配容器化和云原生。
2.3 做事消费方(RPC消费端)做事消费方须要具备可以从注册中央拉取做事列表,缓存做事列表,动态监听和更新做事列表的功能,还须要具备针对付做事的负载均衡策略,序列化和反序列化,根据约定的通信协议进行调用等。
目前Dubbo是基于代理和Spring的BeanDefination来实现的,在消费启动的时候会去扫描基于自定义表明或配置的信息,然后天生一个相应的代理工具,注册到Spring容器中,在调用的时候直接通过代理类进行干系一系列调用。SpringCloud是基于HTTP协议和增强版的RestTemplate来实现的,内部实现了Ribbon的负载均衡,消费方可以通过Feign或者RestTemplate实现远程调用。
2.4 通讯框架通讯框架是做事之间进行IO交互和传输的担保,消费端须要通过通讯框架和供应方进行交互,获取数据,目前市情上主流的基于Java的NIO通讯框架便是Netty。
2.5 通讯协议通讯协议是消费端和做事端约定好一种交互协议,当消费端拿到做事端供应的IO流之后,须要根据通讯协议获取详细的数据内容,目前TCP通讯协议比较通用的是HTTP、FTP、SMTP协议等,SpringCloud是基于HTTP的通讯协议实现的,Dubbo内部自己集成了一套通讯协议。
业界的主流协议的办理方案可以归纳如下:
定长,例如每个报文的大小为固定长度100字节,如果不足用空格补足。在包尾分外结束符进行分割。将分为头和体,头中包含表示总长度(或者体长度)的字段。通过比拟,我们创造第三点是最为灵巧和可拓展的,一样平常推举都会利用第三种。
2.6 序列化2.6.1 观点先容序列化(serialization)便是将工具序列化为二进制形式(字节数组),一样平常也将序列化称为编码(Encode),紧张用于网络传输、数据持久化等。
反序列化(deserialization)则是将从网络、磁盘等读取的字节数组还原成原始工具,以便后续业务的进行,一样平常也将反序列化称为解码(Decode),用于网络传输工具的解码,以便完发展途调用。
2.6.2 序列化协议XML & SOAPXML是一种常用的序列化和反序列化协议,具有跨机器,跨措辞等优点。XML历史悠久,其1.0版本早在1998年就形成标准,并被广泛利用至今,目前金融和银行行业利用较多。
JSONJSON 全称(Javascript Object Notation)起源于弱类型措辞Javascript, 它的产生来自于一种称之为”Associative array”的观点,实在质是便是采取”Attribute-value”的办法来描述工具。实际上在Javascript和PHP等弱类型措辞中,类的描述办法便是Associative array。JSON的具有数据大略,可接管程度高,构造简洁,序列化包体小等特点,目前大部分的公司都是利用这种序列化协议来实现的。
Protobuf由谷歌开拓的一款高性能序列化框架,是一个纯粹的展示层协议,可以和各种传输层协议一起利用,目前支持Java、C++、Python 等多种措辞,他具有更小的数据量,更快的解析速率,大略的调用等特点,目前得物利用的Dubbo2.7.7版本 默认利用这种序列化协议。
2.7 负载均衡负载均衡是担保做事供应方在多实例的情形下担保负载的均衡的一种策略,目前大体有如下几种负载均衡策略:
1)轮训,采取计数器的办法,根据计数器的值和实例数量进行取余。
2)随机,采取随机要求的办法,随机一个Random的数值,根据random进行取余。
3)加权轮训,采取权重的办法,给每一个实例配置不同的权重比例,通过比例选择得当的实例。
4) 同等性Hash,采取Hash环的办法,大体的实现思路是通过寻址的办法找到就近的一个节点,详细可以自行网上搜索一下干系文档理解。
三、实现
既然是当作练手实现一个RPC框架,以是会只管即便借鉴当前主流的框架,技能选型方面:
注册中央:选择Zookeeper来实现。
做事供应方:选择基于做事维度来实现做事创造,目前主流框架都是基于这个来做的。
做事消费方:选择Dubbo类似的基于代理Spring的BeanDefination来实现。
通讯框架:Netty。
通讯协议:采取上述的第三种办法。
序列化协议:支持JSON 和 Protobuf。
负载均衡:实现轮训和随机。
当然,上述的组件都是利用SpringBoot的SPI办法来进行选择的,后续如果须要进行拓展和按不同配置加载,可以通过配置的办法来实现插件的可插拔。
废话不多说,先贴上项目整体构造:
整体代码构造如上,下面针对模块逐一讲解:
3.1 注册中央代码实现如下:
由于我们因此可拓展和接口办法实现的,以是我们定义了一些接口,通过不同的实现来进行区分,后期可以通过不同的配置来选择得当的注册中央。
3.2 做事供应方
做事供应方通过利用Spring的事宜来进行监听,同时根据声明式的表明来进行解析和注册,同时通过组装元数据,将自己的做事注册到注册中央,完成做事供应方的做事注册,同时启动Netty的客户端,来进行客户真个监听,从而进行做事调用,详细流程图如下:
部分实当代码如下:
自动装备逻辑:
利用和做事注册逻辑:
3.3 做事消费方
做事消费方的逻辑轻微繁芜一些,须要通过自动装置来创建新的BeanDefination, 然后从所有的Bean中找到干系的带有RPC表明的参数,重写BeanDefination,重写的Bean须要构建新的元数据和存入客户端缓存,然后通过动态代理的办法,创建一个代理工具,工具利用负载均衡在做事创造的时候选择一个地址,通过Netty的办法进行通信和数据交互,末了返回干系数据工具,详细的流程如下图:
部分实当代码如下:
启动开始类代码:
代理类实当代码:
负载均衡实当代码:(SPI可拓展模式)
目前采取轮训和随机的办法实现的,后期可根据接口进行拓展。
3.4 通讯框架
我们利用Netty4实现了通讯框架,采取了NettyClient和NettyServer来实现:
3.5 通讯协议
我们目前利用了自定义的通信协议来实现:
第一个字节是邪术数,比如我定义为0X35。
第二个字节代表协议版本号,以便对协议进行扩展,利用不同的协议解析器。
第三个字节是要求类型,如0代表要求1代表相应。
第四个字节表示长度,即此四个字节后面此长度的内容是content。
3.6 序列化协议
目前支持JSON和ProtoBuf,后期我们可以通过SPI进行拓展和可配置。
整体核心调用流程:
四、总结
本文从整体名词先容、内部组件组件先容等两个方面阐述了RPC的框架模型,从技能选型、详细代码等实现了一个RPC框架并运用到项目中。目前RPC框架整体搭建完成,可以正常通过表明接入业务方利用,但还有很多细节须要更仔细地去考虑和思虑,比如系统的可拓展性和框架的整体性能等。希望通过阅读本篇文章,可以让读者对RPC有更清晰的理解,让自己的根本技能有一个更高的提升。
文/Wade
关注得物技能,每周一三五晚18:30更新技能干货
假如以为文章对你有帮助的话,欢迎评论转发点赞~