RPC学习笔记
全称是 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会给接口生成一个代理类,运行时绑定这个代理类。调用方法被代理类拦截完成远程过程调用