全称是 Remote Procedure Call,即远程过程调用。简单点理解就是像调用本地一样调用远程方法。

远程调用需要保证业务可靠性,所以RPC一般使用TCP进行传输。

RPC是解决应用间通信的一种方式,经常在微服务中使用。还在MQ、数据库等场景中有使用

RPC协议

RPC请求,需要把请求参数序列化成二进制后,写入本地socket中,然后被网卡发送到网络设备中。

传输过程中,数据可能拆分成几个数据包,也可能和其他请求的数据包合并。为了保持语义一致,需要给请求设定边界,就是所说的协议

和HTTP协议一样,都属于应用层协议。但是RPC协议性能要求相对更高。HTTP协议数据包比较大,而且是无状态协议,每次都需要重新建立连接。

定长协议头一般协议有两部分:协议头、协议体。协议头包含长度、序列化方式、消息ID等,长度固定;协议体放参数和一些扩展属性,长度可变。定长协议头扩展性不好,如果新属性放在协议体里,需要解析性能消耗大。

简答的可扩展协议包含三部分:固定部分,协议头,协议体

序列化/反序列化

参数对象需要序列化成二进制数据进行网络传输。对象转成二进制的过程就是序列化,二进制转成对象的过程就是反序列化

常见序列化

  • JSON:典型的KV方式,额外空间开销大,没有类型
  • gof:和JSON一样是go自带的序列化方式。二进制,反序列化比JSON快,序列化效率低,但均不如pb
  • Protobuf:Google推出,支持多语言,需要定义IDL。速度快、序列化后体积小、可以向后兼容

网络IO模型

常见网络IO模型,最常用的是同步阻塞IO和IO多路复用

  • 同步阻塞IO(BIO)
  • 同步非阻塞IO(NIO)
  • IO多路复用
  • 异步非阻塞IO(AIO)

同步阻塞IO:发起IO调用后被阻塞,等待到数据之后将数据拷贝到内存中。使用难度低,单个开销低

IO多路复用:多个网络IO注册到一个复用器(select)上,调用select时阻塞,select负责的socket有数据时返回。可以在一个线程内同时处理多个IO,更适合高并发场景,但是使用难度较高(高级语言封装简洁)

零拷贝

系统层面:

应用缓冲区、内核缓冲区、网卡之间需要两次拷贝,需要上下文切换(用户进程与系统内核)开销较大

零拷贝有两种解决方式:mmap+write(核心原理是虚拟内存)和sendfile

用户空间的零拷贝:偏向数据,拆分的数据包不进行拷贝,逻辑合并

动态代理

RPC会给接口生成一个代理类,运行时绑定这个代理类。调用方法被代理类拦截完成远程过程调用