四大网络IO模型总结(未完成)

本文最后更新于:2022年11月8日 晚上

概览:常见的网络IO模型总结

常见网络IO模型

  1. 同步阻塞IO(BIO)
  2. 同步非阻塞IO(NIO)
  3. IO多路复用
  4. 异步非阻塞IO(AIO)

只有AIO是异步IO,其他都是同步IO。

同步阻塞IO —— BIO

(最简单最常见的模型)

应用进程发起IO系统调用之后,应用进程被阻塞,转到内核空间处理,之后内核开始等待数据,等待到数据之后,再将内核中的数据拷贝到用户内存中,整个IO处理完成之后返回进程,最后应用的进程解除阻塞状态,运行业务逻辑。

系统内核处理IO分为两步:

  1. 等待数据(系统内核等待网卡接受数据,然后把数据写入内核 – 使用DMA)
  2. 拷贝数据(把系统内核的数据拷贝到用户进程空间)

而此时应用进程则一直处于阻塞状态。

IO多路复用 IO multiplexing

(广泛应用于高并发场景,用较少的进程处理较多的请求,Java NIO、Redis、Nginx、Reactor模式)

IO多路复用分为select、poll、epoll。

多路复用中多路指多个通道,也就是多个网络连接的IO,复用是指多个通道复用一个复用器(select)。

多个网络连接的IO可以注册到一个一个复用器(select)上,当用户进程调用了select,那么整个进程会被阻塞,同时内核会监视所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回,这时用户进程再调用read操作,将数据从内核拷贝到用户进程。

优势:用户可以在一个线程内同时处理多个socket的IO请 –> 用户注册多个socket,然后不断调用select读取被激活的socket,即可达到在同一个线程内同时处理多个IO请求的目的。

零拷贝 Zero-copy

阻塞IO系统内核处理IO分为两步:

  1. 等待数据(系统内核等待网卡接受数据,然后把数据写入内核)
  2. 拷贝数据(把系统内核的数据拷贝到用户进程空间)

可以从流程看到,读数据需要从网卡拷贝到内核缓冲区,然后再从内核缓冲区拷贝到进程缓冲区;写数据也是类似的两个步骤。

应用进程的一次完整的读写操作,需要用户空间和内核空间中来回拷贝,每拷贝一次,都需要CPU进程一次上下文切换,这样很浪费CPU和性能。

而零拷贝,就是取消了用户空间和内核空间之间的数据拷贝操作,应用进程读写数据就像直接在内核空间读写数据一样。

具体实现方式有两种:

  1. 使用虚拟内存mmap+write(虚拟内存直接映射到用户空间)
  2. sendfile方式:直接从磁盘读取到内核,然后内核直接发送到网卡,不需要用户态和内核态的转换拷贝。

以上是操作系统层面的零拷贝,目的是避免用户空间与内核空间之间的数据拷贝操作,可以提升 CPU 的利用率。而Netty中的零拷贝是基于用户空间的,目的是数据操作的优化。

参考链接

极客时间专栏《RPC实战与核心原理》04讲:04 | 网络通信:RPC框架在网络通信上更倾向于哪种网络IO模型? (geekbang.org)


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!