RPC是解决进程间通信的一种方式.一次RPC调用,本质就是服务消费者与服务提供者间的一次网络信息交换的过程.
网络通信是整个RPC调用流程的基础.
常见的网络IO模型
两台PC机之间的网络通信,世纪上就是两台PC机对网络IO的操作.
常见的网络IO模型分为四种:同步阻塞(BIO)\同步非阻塞(NIO)\IO多路复用和异步非阻塞(AIO)
最常用的是同步阻塞IO和IO多路复用
阻塞IO(blocking IO):
等待数据和拷贝数据
IO多路复用(IO multiplexing):
为什么说阻塞IO和IO多路复用最为常用?
网络IO应用都需要系统内核的支持以及编程语言的支持,阻塞IO和IO多路复用系统内核与编程语言支持最为完善.
RPC框架在网络通信上倾向选择哪种网络IO模型?
IO多路复用更是和高并发场景,可以用较少的进程(线程)处理较多的socket的IO请求,但是难度高
阻塞IO每处理一个socket的IO请求都会阻塞进程(线程),但难度低.
RPC调用是一个高并发场景,考虑内核\编程语言的支持以及IO模型本身特点,我们选择IO多路复用的方式
零拷贝(Zero-copy)
等待数据: 系统内核在等待网卡接收到数据后,把数据写到内核中
拷贝数据: 系统内核在获取到数据后,将数据拷贝到用户进程的空间中
应用进程的一次完整的读写操作,都需要在用户空间与内核空间中来回拷贝,并且每一次拷 贝,都需要 CPU 进行一次上下文切换(由用户进程切换到系统内核,或由系统内核切换到 : 用户进程)
取消用户空间与内核空间之间的数据拷贝操作,应用进程每一次的读写 操作,可以通过一种方式,直接将数据写入内核或从内核中读取数据,再通过 DMA 将内 核中的数据拷贝到网卡,或将网卡中的数据 copy 到内核.
实现:用户空间与内核空间都将数据写到同一个地方(虚拟内存)
零拷贝有两种解决方式,分别是 mmap+write 方式和 sendfile 方式
操作系统层面零拷贝,主要目标是避免用户空间与内核空间之间的数据拷贝操作,可以提升CPU的利用率.
Netty中的零拷贝
用户空间对数据的零拷贝,处理 TCP 传输中的拆包粘包问题有着重要的意义
Netty 的 ByteBuffer 可以采用 Direct Buffers,使用堆外直接内存进行 Socketd 的读写 操作,可以解决用户空间与内核空间间的数据拷贝.