RPC原理分析

505 阅读4分钟

0 rpc在微服务中的位置

image.png

可以说 RPC 对应的是整个分布式应用系统,就像是“经络”一样的存在。如果应用是微服务方式部署的,那么RPC就是微服务之间连接的纽带。

1 RPC的协议

image.png

我们回滚下五层网络模型,每一层都有相关的传输对象和一些协议,因此准确来说,面试的时候如果面试官问RPC协议一般指的是应用层的协议。 应用层协议 (application layer protocol)定义了运行在不同端系统上的应用程序进程如何相互传递报文

我们理解网络在应用层的协议是一种约定,基于这样的约定,数据能够端到端正确的传输。就好比全国人民都说方言,但是可以利用中文简体书写或者普通话作为沟通的协议,不然不通地方的人都不能正常交流,没有协议都会乱套。

2 为什么很多RPC框架使用私有协议

应用层已经有http这种现成的协议,为啥很多rpc组件还是设计自己的私有协议呢。

  • HTTP 协议属于无状态协议,客户端无法对请求和响应进行关联,每次请求都需要重新建立连接,响应完成后再关闭连接。rpc客户端和服务端可以通过服务注册和发现进行确定。
  • HTTP 协议的数据包大小相对请求数据本身要大很多,又需要加入很多无用的内容,比如换行符号、回车符等;rpc对性能要求比较高。
  • RPC 为了吞吐量,会异步并发发送请求,实现请求跟响应关联。而Http不能做到这一点。RPC调用方需要维护消息ID列表,然后和返回结果中的消息ID做匹配。

设计一个可扩展RPC协议,

  1. 使用固定位存储协议参数
  2. 通过消息ID来做请求和响应的绑定。
  3. 设计不固定的协议头扩展字段,避免扩展时需要在协议体中进行序列化解析;比如超时信息,直接返回超时而不是解析协议体浪费cpu资源。 整体协议就变成了三部分内容:固定部分、协议头内容、协议体内容,前两部分我们还是可以统称为“协议头”,具体协议如下: image.png

3 序列化

序列化就是将对象转换成二进制数据的过程,而反序列就是反过来将二进制转换为对象的过程。 image.png

为网络传输的数据必须是二进制数据,所以在 RPC 调用中,对入参对象与返回值对象进行序列化与反序列化是一个必须的过程。 image.png

常见的序列化类型

  1. JDK自带序列化
  2. JSON
  3. Hessian
  4. Protobuf

考虑性能,可以无脑上PB。如果对性能不敏感,可以用JSON,可读性较好。 image.png

4 IO模型

网络通信中可以使用的IO模型有 同步阻塞 IO(BIO)、同步非阻塞 IO(NIO)、IO 多路复用和异步非阻塞 IO(AIO)。在这四种 IO 模型中,只有 AIO 为异步 IO,其他都是同步IO。 具体IO模型介绍移步 # IO模型

5 动态代理

我们在使用RPC的时候通过maven包的形式将接口依赖进来,通过依赖注入的方式把接口注入到项目中就行了,然后在代码里面直接调用接口的方法。方法实现的细节对于调接口的人来说是透明的,这主要是通过动态代理技术实现的。

RPC框架基于动态代理技术,在调用时(运行时)针对目标调用类生成代理对象,实现对远程服务上的方法的调用。动态代理是一种字节码增强的技术,如果是CGlib实现的,就要求目标类不能被final关键字修饰。 动态代理可以在不变更原有代码的情况下,通过代理类调用远程服务上的方法。 image.png

6 可扩展的RPC架构

image.png 一个完备的RPC框架包含上图的这些模块,但是为了更好的扩展,将上图的架构改成插件化的架构。加上了插件功能之后,我们的 RPC 框架就包含了两大核心体系——核心功能体系与插件体系。这时,整个架构就变成了一个微内核架构,我们将每个功能点抽象成一个接口,将这个接口作为插件的契约,然后把这个功能的接口与功能的实现分离并提供接口的默认实现。

image.png

参考

图解IO多路复用