当前位置: 首页 > 科技观察

用浅显易懂的语言介绍RPC框架的架构原理

时间:2023-03-19 15:02:30 科技观察

本文转载自微信公众号《会笑的架构师》,作者雷小帅。转载本文,请联系LoveSmile的架构师公众号。2022认真做点事!手工实现一个简单的RPC轮子真的很难吗?不不不,很简单。如果您不相信我,请阅读文章(doge)。实战RPC框架典型架构一个典型的RPC架构大致可以分为三个部分:(1)服务提供者(RPCServer):运行在服务器端,提供服务接口定义和服务实现类。(2)Registry:运行在服务器端,负责将本地服务发布为远程服务,管理远程服务,提供给服务消费者。(3)服务消费者(RPCClient):运行在客户端,通过远程代理对象调用远程服务。从上图可以看出,一个简单的RPC调用可以分为以下几个步骤:(1)服务提供者启动后,主动向服务注册中心注册机器ip、端口和提供的服务列表;(2)服务消费运营商启动时,从服务注册中心获取服务提供者的地址列表,并在本地缓存一份;(3)服务消费者通过本地调用调用服务,调用模块接收到请求后,通过负载均衡策略选择合适的远程服务地址;(4)协议模块负责序列化(编码)信息如将方法和输入参数写入可通过网络传输的消息体中,通过网络将消息发送给服务器;(5)服务器收到消息后进行解码(反序列化操作)。(6)根据解码结果调用本地服务进行相关处理;(7)服务端对处理返回的结果进行序列化(编码)处理,通过网络将结果发送给服务消费者;(8)服务消费者收到消息后进行解码,最终得到结果;敲黑板:步骤1、2、3的顺序在不同的RPC框架实现中可能有些不同。RPC核心功能一个完整的商业RPC框架有很多功能,其中最核心的是三个:服务寻址、数据编解码、网络传输。如果服务寻址是本地调用,被调用的方法在同一个进程中,操作系统或虚拟机可以在地址空间中找到;但是在远程调用中,这是行不通的,因为两个进程的地址空间是完全不一样的,而且没有办法知道远程进程在哪里。实现远程调用需要对服务消费者和服务提供者进行约束:远程过程调用中的所有函数都必须有一个ID,这个ID在整个系统中是唯一确定的。当服务消费者进行远程过程调用时,发送的消息体必须携带此ID。服务消费者和服务提供者分别维护一个对应的功能表和ID表。当服务消费者需要进行远程调用时,会查表找到对应的ID,然后传递给服务端。服务器端也会通过查表来确定客户端需要调用的函数,然后执行相应的函数。函数的代码。我上面提到的可能是抽象的。通俗一点就是服务消费者如何找到服务提供者。这是服务寻址。服务寻址的实现方式有很多种,比较常见的一种是:服务注册。调用一个服务首先需要一个服务注册中心查询对方服务有哪些实例,然后根据负载均衡策略选择最好的一个。类似Dubbo框架的服务注册中心是可配置的,官方推荐使用Zookeeper。数据编解码(序列化和反序列化)对计算机网络稍有了解的同学都知道,数据在网络中传输是二进制的:01010101010101010,与此类似,在网络中只能传输二进制数据。当客户端调用远程服务的方法时,如方法的输入参数必须转换成二进制进行传输。这种将对象转换为二进制流的过程称为序列化编码。如果服务器接收到二进制流而无法识别,则必须将二进制流转换为对象。这个相反的过程称为反序列化和解码。在一般场景下,序列化编码可以简称为序列化。敲黑板:非要说正经的话,严格来说,序列化和编码是两个不同的概念。我画个图,大家就明白了。序列化和编码的比较序列化+编码的逆过程是:解码+反序列化。网络传输一提到网络传输,大家马上就会想到TCP/IP四层模型和OSI七层模型。通常,RPC选择哪一层作为传输协议?在回答这个问题之前,我们先看看RPC需要网络传输实现什么功能。客户端的数据经过序列化和编码后,需要通过网络传输到服务端。网络传输层需要将上述函数ID和序列化后的参数字节传给服务器,服务器处理后将序列化后的调用结果返回给客户端。原则上只要能实现上述功能,就可以作为传输层使用,具体协议不限。我们先来看TCP协议。TCP连接可以是按需连接。当需要调用时,会先建立,调用完后立即断开。它也可以是一个长期的连接。是的,无论此时是否有数据包发送,都可以配合心跳检测机制,周期性检测建立的连接是否存活有效。可见TCP的性能确实不错,所以市面上的RPC框架大多使用TCP协议,但也有少数框架使用其他协议,比如gRPC就是基于HTTP2实现的。敲黑板:数据编解码和网络传输可以有多种组合方式,比如:HTTP+JSON、Dubbo协议+TCP等常见的RPC框架说了这么多RPC相关的技术,我们来看看市面上常用的RPC框架。RMI(Sun/Oracle)Thrift(Facebook/Apache)gRPC(Google)Finagle(Twitter)Dubbo(阿里巴巴/Apache)Motan(新浪微博)brpc(百度/Apache)......欢迎补充。总结(1)服务提供者需要以某种形式提供与服务调用相关的信息,包括但不限于服务接口定义、数据结构或中间服务定义文件。例如Facebook的Thrift框架的IDL文件和Web服务的WSDL文件;服务消费者需要通过某些场景获取远程服务调用的相关信息。(2)远程代理对象:服务消费者使用的服务实际上是远程服务的本地代理。说白了,就是通过动态代理来实现的。(3)序列化:毕竟是远程通信,需要将对象转换成二进制流进行传输。不同的RPC框架有不同的应用场景,采用不同的技术进行序列化。(4)通信:RPC框架与具体的协议无关。Netty是一个高性能的网络通信框架。因此,要实现一个RPC框架,只需要实现以上四点就可以基本完成。你学会了吗?