Netty学习-IO编程

Netty学习-IO编程

二月 06, 2020

UNIX常见I/O模型

基本说明

使用通道进行数据的发送和接收, 程序通信的性能取决于什么样的通道.

对于一次IO访问,数据会先被拷贝到操作系统内核的缓冲区中,然后再从操作系统内核的缓冲区拷贝到应用程序的地址空间。

当发生一个IO操作时,它会经历两个阶段: 1. 等待数据准备 2. 将数据从内核拷贝到进程中


BIO(blocking I/O):

同步并阻塞模型, 为传统io模型, 主要模式为一个连接一个线程, 即当客户端有 连接请求时服务端才开启一个线程进行处理.

BIO的特点就是在IO执行的两个阶段都被锁住了


NIO(non-blocking I/O):

同步非阻塞模型, 一个线程处理多个请求, 即客户端发送的请求先注册在多路复用器上,多路复用器经过轮询,遇到I/O请求就进行处理. NIO三个核心对象:通道(Channel)缓冲区(Buffer)选择器(Selector)

用户发出io请求后, 如果第一阶段的内核数据还没有准备好, 用户进程不会进入等待(不会被锁住), 服务端会立即返回一个error, 用户进程收到结果后会不断的去请求, 直到内核数据准备好, 然后进入第二阶段, (注:但是第二阶段依然会有锁住的情况, NIO只是在数据准备阶段非阻塞)

所以特点是需要不断的主动询问kernel数据准备好了没有


IO多路复用(I/O multiplexing):

I/O多路复用模型, 又名事件驱动模型, 使用了Reactor设计模式来实现,就是我们用的select,poll,epoll。当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。简单的说,就是和阻塞IO处理方式一样,但不同的是,select可以一下把很多很多文件描述符都传过来,然后操作系统内核同时监视他们,只要其中一个就绪,就及时处理那个,而不需要一个个等待处理。

select、pselect、poll、epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的(异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。)

因而IO多路复用的性能可能比阻塞IO还要差,但他的优点在于能同时处理多个连接,相比较于同步非阻塞I/O,它的改进的地方在于,原来需要用户进程去轮询的这事儿交给了内核线程帮你完成, 而且这个内核线程可以等待多个socket,能实现同时对多个IO端口进行监听。所以,如果处理的连接数不是很高的话,使用IO多路复用不一定比使用多线程+阻塞IO的性能更好,可能延迟还更大。


AIO(Asynchronous I/O):

异步非阻塞, AIO 引入异步通道的概念, 采用Proactor模式, 出现有效的请求才启动线程, 特点是先由操作系统完成后才会通知服务端 程序去启动线程处理,适用于连接数较多且连接时间较长的应用.

同步/异步IO,阻塞/非阻塞IO

阻塞、非阻塞说的是调用者(Client)。同步、异步说的是被调用者(Server)。

阻塞/非阻塞: 一个IO请求,在线程中进行,当这个IO请求没有数据或者没有有效数据拉来完成IO操作,那么这个请求不会结束,而是等待,而这个等待就是阻塞,因为他在等待数据,导致其他IO操作无法进行, 反之则为非阻塞.

同步/异步: 同步/异步IO的区分是针对完成实际的IO操作,笼统的说,同步IO就是应用程序完成实际的IO操作,而异步IO就是将实际的IO操作交给操作系统去完成

总结

阻塞IO:用户一直等操作系统内核完成2个阶段io操作,再继续

非阻塞IO:第一阶段用户一直问操作系统有没有准备好,第二阶段等操作系统完成。

IO多路复用:用户进程可以同时发多个网络连接IO,操作系统实施监控,虽然用户进程2个阶段都卡住了,但可以处理多个连接。

异步IO:用户进程完全把东西交给操作系统完成,自己不管了。