1 . IO的演变和Reactor模式

Linux中5中I/O模型:同步阻塞I/O、同步非阻塞I/O、I/O多路复用、信号驱动 I/O 、异步非阻塞I/O

对于同步阻塞I/O来说,传统java中的Socket I/O都是基于BIO模型,也就是所谓的Blocking I/O(同步阻塞式I/O)。当我们在进行I/O相关操作式,执行线程都是阻塞等待内核返回相应的I/O数据,如果没有I/O数据,一直等待。执行线程要想获得I/O的结果,必须阻塞等待,直到内核通知线程有数据到来,执行线程去读取数据,然后进行相应的处理。

在上述连接的模式下,Java开始采用了一个线程对应一个连接,去处理对应的I/O事件。这种编程模型在连接量少的时候是完全可以胜任的。在互联网早期,并发连接的数量一般不会太大,这种模式简单,能够满足早期的需求。但是随着互联网的发展,并发连接的数量越来越大,这种模式越来越局限,最大的问题在于是线程资源的局限。在现代的系统中,线程的资源是比较宝贵的,这种BIO多线程模式下,一个连接一个线程,成千上万个连接就会对应创建成千上万个线程,系统会变得异常缓慢。

对于同步非阻塞I/O来说,每次执行线程去调用内核来获取数据时,并不会阻塞,而是不管有无数据立马返回,如果没有数据会返回一个error回来。如果有数据,内核在读取数据并复制到用户空间。需要注意的是,内核读取数据这步依然是阻塞的。

对于I/O复用来说,依赖的实际上是系统内核更新后提供的select/epoll内核函数,从另外一个方面来说,可以说是基于事件的。当socket连接建立之后,将socket连接对应的文件句柄注册到一个所谓的I/O复用器上(selector),然后由内核对这个复用器执行检察操作(不会阻塞执行线程)。当I/O事件发生,则会改变I/O复用器上对应socket的相关状态,这样当执行线程调用select获取复用器上socket的状态的时候(这步会阻塞),能够立马直到那些socket可读,这样执行线程再去读取那些可以读取数据的socket。

对于信号驱动I/O来说,相当于是在socket上建立信号处理,当socket发生相关事件时,通过信号的传递,在信号处理函数中进行对应的处理。

对于一部非阻塞I/O来说,实际上是将上面的整个过程都交由内核来进行处理了,这样执行线程可以去执行其他逻辑,当内核执行好后,会给执行线程发送一个信号,执行线程在来进行相应的I/O处理。

提到Reacotr模式,就不得不提 Doug Lea的著名文档 Scalable IO in java http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf。现在基本上绝大多数注重I/O的中间价采用的都是这种模式,如 redis,nginx。

Reacotr模式,也称反应器模式,是一种事件驱动型同步I/O,其思想是,将原有I/O的处理进行了职责的划分,分为Reactor和Handler两部分,其中Reacotr用来同步阻塞监听I/O相关事件,Handler用来处理非阻塞的相关行为。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值