各种IO模型,一篇打尽
Posted 支付技术那些事
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了各种IO模型,一篇打尽相关的知识,希望对你有一定的参考价值。
一、阻塞/非阻塞-同步非同步
同步/异步
同步请求:A调用B,B的处理是同步的,在处理完之前他不会通知A,只有处理完之后才会明确的通知A;
异步请求:A调用B,B的处理是异步的,B在接到请求后先告诉A我已经接到请求了,然后异步去处理,处理完之后通过回调等方式再通知A。
同步/异步区别
同步和异步最大的区别就是被调用方的执行方式和返回时机;
同步指的是被调用方做完事情之后再返回;
异步指的是被调用方先返回,然后再做事情,做完之后再想办法通知调用方。
阻塞/非阻塞
阻塞请求:A调用B,A一直等着B的返回,别的事情什么也不干;
非阻塞请求:A调用B,A不用一直等着B的返回,先去忙别的事情了。
阻塞/非阻塞区别
阻塞和非阻最大的区别就是在被调用方返回结果之前的这段时间内,调用方是否一直等待。
阻塞指的是调用方一直等待,别的事情什么都不做;
非阻塞指的是调用方先去忙别的事情。
阻塞/非阻塞和同步/异步的区别
阻塞、非阻塞和同步、异步其实针对的对象是不一样的
阻塞、非阻塞说的是调用者
同步、异步说的是被调用者
二、Linux(UNIX)操作系统五种IO模型
什么是IO
拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目的是把它读取到内存中。可以把这个步骤简化成把数据从硬件(硬盘)中读取到用户空间中。
一次完整的钓鱼(IO)操作,是鱼(文件)从鱼塘(硬盘)中转移(拷贝)到鱼篓(用户空间)的过程。
阻塞IO模型
阻塞 I/O 是最简单的 I/O 模型,一般表现为进程或线程等待某个条件,如果条件不满足,则一直等下去。条件满足,则进行下一步操作。
应用程序进行 recvfrom 系统调用时将阻塞在此调用,直到该套接字上有数据并且复制到用户空间缓冲区。该模式一般配合多线程使用,应用进程每接收一个连接,为此连接创建一个线程来处理该连接上的读写以及业务处理。
非阻塞IO模型
应用进程与内核交互,目的未达到之前,不再一味的等着,而是直接返回。然后通过轮询的方式,不停的去问内核数据准备有没有准备好。如果某一次轮询发现数据已经准备好了,那就把数据拷贝到用户空间中。
应用进程通过 recvfrom 调用不停的去和内核交互,直到内核准备好数据。如果没有准备好,内核会返回error,应用进程在得到error后,过一段时间再发送recvfrom请求。在两次发送请求的时间段,进程可以先做别的事情。
IO复用模型
多个进程的IO可以注册到同一个管道上,这个管道会统一和内核进行交互。当管道中的某一个请求需要的数据准备好之后,进程再把对应的数据拷贝到用户空间中。
IO多路转接是多了一个select函数,多个进程的IO可以注册到同一个select上,当用户进程调用该select,select会监听所有注册好的IO,如果所有被监听的IO需要的数据都没有准备好时,select调用进程会阻塞。
信号驱动IO模型
应用进程在读取文件时通知内核,如果某个 socket 的某个事件发生时,请向我发一个信号。在收到信号后,信号对应的处理函数会进行后续处理。
异步IO模型
应用进程把IO请求传给内核后,完全由内核去操作文件拷贝。内核完成相关操作后,会发信号告诉应用进程本次IO已经完成。
5种IO模型对比
三、Java中的三种IO模型
java IO模型和操作系统IO模型关系
Java中的IO还是借助操作系统的IO模型的,只不过是对操作系统IO模型的封装而已啦。
可以把Java中的BIO、NIO和AIO理解为是Java语言对操作系统的各种IO模型的封装。
java中提供的IO有关的API,在文件处理的时候,其实依赖操作系统层面的IO操作实现的。
比如在Linux 2.6以后,Java中NIO和AIO都是通过epoll来实现的,而在Windows上,AIO是通过IOCP来实现的。
阻塞IO(BIO)
同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。
BIO (Blocking I/O):有一排水壶在烧开水,BIO的工作模式就是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。
BIO和NIO都是同步的IO模型,即同步阻塞IO和同步非阻塞IO
非阻塞IO(NIO)
同时支持阻塞与非阻塞模式,但主要是使用同步非阻塞IO。
NIO (New I/O):NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。
异步IO(AIO)
异步非阻塞I/O模型。
异步IO指的是异步非阻塞IO。
AIO ( Asynchronous I/O):为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。
四、Reactor 模式
Reactor 模式跟 IO 模型关系
Reactor 模式跟 IO 模型中的 IO 多路复用模型非常相似
IO 多路复用模型可以看成是 Reactor 模式在 IO 模型上的应用
Reactor 模式在进程-线程模型上的应用。
1. 单进程单线程
只有一个进程,监听套接字和连接套接字上的事件都由 Select 来处理。
过程
(1) 如果有建立连接的请求过来,Acceptor 负责接受并与之建立连接,同时将连接套接字加入 Select 进行监听。
(2) 如果某个连接上有读事件则进行 Read->业务处理->Write 等操作。
(3) 如此循环反复。
缺点:会有阻塞,在进行业务处理的时候不能进行其他操作:如建立连接,读取其他套接字上的数据等。
2. 单进程多线程
与单进程单线程类似,不同的是该模型将业务处理放在线程中,进程就不会阻塞在业务处理上。
优点:比较完美的进程-线程模型,在 Java 实现中复杂度也不高,很多网络库都是基于此,比如 Netty 。
3. 多进程单线程
与非 Reactor 模式中的多进程单线程相似,只是本模式在子进程中使用了 IO 多路复用,实用性一下就上来了。大名鼎鼎的 nginx 就采用这种进程-线程模型。
缺点:子进程还是会阻塞在业务处理上。
4. 多进程多线程
5. 主从进程多线程
前面几种 Reactor 模式的进程-线程模型中,连接的建立和连接的读写都是在同一进程中。本模型中将连接的建立和连接读写放在不同的进程中。
过程
(1) 主进程在监听套接字上 Select 阻塞,一旦有请求过来则与之建立连接,并将连接套接字传递给从进程。
(2) 从进程在连接套接字上 Select 阻塞,一旦连接上有数据过来则进行 Read,并将业务通过线程来处理。如果有必要还会向连接 Write 数据。
五、常见组件使用的模型
netty-主从-多线程
tomcat-单进程多线程
redis-单进程单线程
ngnix-多进程单线程
以上是关于各种IO模型,一篇打尽的主要内容,如果未能解决你的问题,请参考以下文章