Netty-1 IO网络模型

名词解释

1
2
Linux 内核会将所有外部设备都看做一个文件来操作,对一个文件的读写操作会调用内核提供的系统命令,返回一个file descriptorfd, 文件描述符)。二队一个socket的读写也会有相应的描述符,成为socketfd,描述符就是一个数字,它指向内核中的一个机构提(文件路径,数据区等一些属性)。
根据UNIX网络编程对I/O模型的分类,UNIX提供了5I/O模型

主体内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.同步阻塞I/O模型(BIO):
传统的BIO模型, 通常由一个独立的Acceptor线程负责监听客户端的链接,塔基收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理,处理完之后,通过输出流返回应答给客户端,线程销毁。
该模型最大的问题就是当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数成1:1的正比关系。可能会导致线程耗尽。

2.同步非阻塞I/O模型(NIO)
此处的NIO并非javanio框架,socket链接默认是阻塞模式,可以通过设置将socket变成为非阻塞的模式。
这种模式下,当用户线程发起IO操作时,内核缓冲区没有数据的情况下,系统调用会立即返回EWOULDBLOCK失败,用户线程需要一直轮训发起IO操作,当有数据时,用户线程进行IO调用此时会进入阻塞状态。

3.I/O多路复用
通过select/epoll系统调用,一个进程(Selector)可以监视多个文件描述符(channel)(fd,一旦某个描述符就绪,内核能够将就绪的状态返回给应用系统(SelectionKey)。用户线程根据就绪状态发起IO调用。
4.信号驱动I/O模型(未理解)
信号驱动的 I/O 模型是一种异步 I/O 模型,它允许应用程序在等待 I/O 操作完成时继续执行其他任务。在这种模型中,当应用程序发起一个 I/O 操作时,它并不会一直等待操作完成。相反,它会注册一个信号处理程序,该处理程序在 I/O 操作完成时被调用。这意味着,当 I/O 操作完成时,内核会发送一个信号告知应用程序,应用程序可以在信号处理程序中获取 I/O 操作的结果。信号驱动的 I/O 模型适用于大量的 I/O 操作,因为它可以同时处理多个 I/O 操作,而不必等待一个操作完成后才开始下一个操作。
5.异步I/O模型(未理解)
应用程序通过异步调用发起 IO 操作,并在操作完成时通过回调函数得到结果。无需额外创建信号处理函数或线程/进程,因此可以大大降低系统的资源消耗和复杂度,并且在高并发场景下可以更加有效地利用系统资源保证程序的性能和可伸缩性。

IO执行的过程中看,信号驱动的 IO 模型只有前半部分实现了异步,而异步IO模型则在整个IO操作过程中都是异步的。所以,相对于信号驱动的 IO 模型,异步 IO 模型在高并发场景下优势较大,可以更好地适应高并发、高负载的应用程序需求。

扩展内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. JAVA I/O演进历史
1jdk1.4之前 采用BIO模式
2jdk1.4 发布基于I/O多路复用的NIO
3jdk1.7 发布NIO2.0,支持AIO(异步I/O操作),Netty并没有使用AIO
2. 用户线程和系统内核的交互
用户程序不直接和内核交互,而是通过缓冲区来进行交互,流程如下:
1)等待数据从网络上到达网卡,当所等待的数据到达时,他被复制到内核中的某个缓冲区。这个工作由操作系统自动完成。
2)就是把内核缓冲区的数据复制到进程缓冲区。JAVA 举例

客户端请求:Linux通过网卡读取客户端的请求数据,将数据读取到内核缓冲区。
获取请求数据:JAVA服务器通过read系统调用,从linux内核缓冲区读取数据,再送入JAVA进程缓冲区。
服务端业务处理:JAVA服务器在自己的用户空间中处理客户端的请求。
服务端返回数据:JAVA服务器完成处理后,构建好的响应数据,讲这些数据通过write操作用户缓冲区写入内核缓冲区,
发送给客户端:LInux内核通过网络IO,将内核缓冲区中的数据写入网卡,网卡通过底层网络协议,将数据发送给客户端。