简介
什么是RPC
RPC(Remote Procedure Call) 即远程过程调用,是一种计算机通信协议。通过 RPC 可以调用远程计算机上运行的程序,而这个过程就像是在进行本地调用一样(不需要关心内部细节)。
RPC 是一种客户端-服务器(Client/Server)模式,经典的实现是通过发送请求-获取响应进行数据交互。
为什么需要RPC
其实对于一个单一应用程序,逻辑简单、用户不多、流量不大,那确实没必要使用 RPC 。
但是,随着业务增大,单机系统可能无法满足需求,此时需要将应用拆成多个独立的小模块,分别运行在不同的机器上。
对于运行在不同设备上的程序,不能像 SDK 一样引入本地依赖直接使用,那就必须通过网络进行交互。
- 服务提供方:需要针对业务对外暴露特定的接口服务
- 服务消费者:每个服务都需要手动构造响应的网络请求
- 双方必须事先约定好有哪些接口、使用哪个网络协议进行传输、数据使用什么格式序列化等等
难道用 RPC 之后就不存在中间这些步骤了吗?是也不是!
RPC 本质上还是一个 C/S 模式应用程序,只不过它把中间的这些步骤做了一层封装。
- 服务器只将实现的服务注册后启动服务器
- 客户端可以像本地调用一样,无感的实现业务逻辑
- 由 RPC 框架来实现内部的通信细节,对双方而言是透明的
实现思路
基本设计
我们已经知道了一个使用 RPC 的项目可以分为三个部分,服务的提供者、服务的消费者以及 RPC 框架本身。
RPC 框架封装了网络通信的细节,即必须在 RPC 框架中集成 C/S
通信模型,可以基于 HTTP
协议实现,也可以直接跑在 TCP
协议之上。
数据需要通过网络发送给对方,但普通对象是无法直接在网络中进行传输的,必须进行序列化与反序列化
- 序列化:将普通对象转换成可以在网络中传输的字节序列
- 反序列化:将字节序列转换成能被编程语言操作普通对象
用多种序列化和反序列化的方案可以任意选择,比如 JSON
、Protobuf
、Hessian
等。

RPC 最重要的一个能力是可以像在进行本地调用一样得到远程的服务!所以,在消费者和提供者之间存在公共的依赖,包括接口、模型等。
- 提供者是真正实现公共接口的一方
- 消费者是使用公共接口的一方
问题来了,消费者手上只有接口,要怎么使用远程的实现方法呢?这时候就可以使用动态代理针对接口生成虚拟代理类,通过反射机制将消费者调用的方法、参数等全都打包发送到服务提供者。
服务器收到请求后,需要进一步处理请求,才能做出针对性的响应。
服务器提供统一的服务接口,客户端的请求将通过 请求处理器
得到所传递的参数,针对不同参数调用不同的服务和方法。
可以在服务端维护一个 服务注册器
用于记录服务所对应实现类的映射。
至此,一个 RPC 框架的基本功能就已经都实现了
扩展设计
简易的实现只需要最基本的核心功能就够了,如果想实现一个优秀的 RPC 框架就需要考虑更多细节。例如:
- 消费者可能不知道提供者的调用地址,就需要一个服务注册中心
- 如果有多个服务提供者,就需要负载均衡机制
- 如果消费者调用服务失败了,也需要有容错机制
- 如果服务提供者下线了,需要一个失效节点剔除机制
- ……