调研
在开发一个RPC 框架之前,一般需要搞清楚以下几个问题
1、开发效率问题
开发效率是所有的框架都需要解决的基础问题,框架的初衷几乎都是为了提高开发效率,避免每次 RPC 调用都要进行重复的 socket 操作、序列化与反序列化处理、解析协议、寻址处理、异常处理等等。因此,一个好的RPC框架应该是对开发友好的,不能让开发进行重复性的工作
2、通信效率问题
作为一款高性能的 RPC 框架,通信效率肯定是要求非常高的。众所周知,客户端和服务端之间的通信,一般都是很快的,但是在考虑到成千上万的请求并发时,应该怎样提高通信效率呢?有很多选择:多线程、流式、多路复用等等。
3、通用化
业务开发的场景是各种各样的,使用框架的姿势也是多种多样的,因此一个好的RPC 框架应该是通用化的。所以设计之初应该有两点基本要求:
- 所有的组件都是可插拔的
- 所有的组件都是支持业务自定义的。
RPC定义
RPC 协议包括 5 个部分:
- Client
- Client-stub
- RPCRuntime
- Server-stub
- Server
这里面分了三个层次:
- 对于客户端和服务端,都像是本地调用一样,专注于业务逻辑的处理就可以了。
- 对于 Stub 层,处理双方约定好的语法、语义、封装、解封装。
- 对于 RPCRuntime,主要处理高性能的传输,以及网络的错误和异常。
模块划分
服务定义
一般来说,当前所有的框架对一个服务的定义大致可以分为两种方式:
- 通过代码定义服务
- 通过配置文件定义服务
两者本质其实都是一样的,通过配置文件定义的话,就需要框架提供一个自动生成脚手架代码的工具而已。
数据序列化
序列化就是将数据结构或对象转换成二进制的过程,也就是编码的过程,序列化后数据才方便进行网络传输;反序列化就是在序列化过程中所生成的二进制转换成数据结构或者对象的过程,将二进制转换为对象后业务才好进行后续的逻辑处理。
常见的序列化协议如下
- protobuf(IDL)
- json
- xml
网络协议
在数据被序列化为二进制后就可以行网络传输了,网络传输就是我们的数据怎么传输到对方服务器上,目前来说,常见的通信传输方式包括 :TCP、UDP、HTTP(HTTP2.0)、QUIC 协议,TCP 是大部分框架都会默认支持的。
编解码
也就是对数据序列化的处理过程
服务治理
一个功能完备的rpc框架一般都会提供一些服务治理相关的基础配套功能
插件化
也就是现在比较流行的微内核架构,我们将每个功能点抽象成一个接口,将这个接口作为插件的契约,然后把这个功能的接口与功能的实现分离并提供接口的默认实现。任何三方或者个人都可以提供自己的视线来替换掉框架中的某部分。