【Node.js】如何理解非阻塞I/O模式


NodeJs有三大特性:
单线程、非阻塞I/O、事件驱动 三者缺一不可,共同组成了神奇的Node


非阻塞 I/O,也叫异步 I/O,显然对应的就是阻塞式 I/O。

传统的服务器语言大多是多线程、阻塞式 I/O。这也是Node与众不同的地方,对于传统的服务器语言,在与用户建立连接时,每一个连接都是一个线程。当有十万个用户连接时,服务器上就会有十万个线程。

而阻塞式 I/O 是指,当一个线程在执行 I/O 操作时,这个线程会阻塞,等待 I/O 操作完成后继续执行。

—————————————————————————————————
———— 什么是多线程,阻塞I/O? ———— [ 一对一服务 ]
—————————————————————————————————

比如我们到一个餐馆吃饭,这个餐馆比较高级,服务员是一对一服务(每个用户都是一个线程),从我们坐下开始,服务员就把菜单给你,然后在旁边等你点菜(等待 I/O 操作),当你看完菜单,把要点的菜告诉服务员( I/O 操作结束后线程继续执行)。在你看菜单的过程中,服务员其实是被闲置的,如果你一直看,他就会一直等,直到你点完( I/O 操作结束), 这就是阻塞式 I/O.

阻塞式 I/O 必须要多线程,就这个例子来看,如果只有一个服务员(单线程),那当店里同时有十个顾客时,他需要一个一个等待顾客看菜单然后点菜,那后面的顾客要等待的时间就会很长,显然这个餐馆的服务就会很差(服务器性能差).

所以传统的服务器都是多线程、阻塞式 I/O,也就是相当于有多个服务员(线程),每个进来的顾客都分配到一个服务员(线程),然后你看菜单时在旁边等候(阻塞式 I/O )。很明显这样的服务是让顾客最舒服的,但是对于餐馆老板来说很难受,因为要雇佣大量的服务员。因此传统的方式成本是比较大的。要有性能足够好的服务器才能支撑大量的线程。但他的优点也很明显,比如某一桌客人与服务员发生争吵(线程崩了!),不会影响到其他顾客,因为每一桌都有专门的服务员负责,因此只会对当前用户产生影响.

—————————————————————————————————
———— 什么是单线程,非阻塞I/O? ———— [ 一对多服务 ]
—————————————————————————————————

node 最大的优势就是性能强,同样的服务器性能使用 node 可以比传统的服务器语言多容纳一百倍的用户(对于不同的任务有不同的差别, I/O 操作越多,node优势越明显,如果都是 CPU 计算任务,那他俩几乎没有区别(上面的例子中,忽略顾客的看菜单时间)

上面的例子,这应该是个规模比较小的餐馆,或者说老板比较穷,雇不起大量的服务员,因此只能雇佣一个服务员。当有顾客来时,服务员把菜单送过去,顾客开始看菜单( I/O 操作),这个时候,服务员是被释放了的,他不用等待顾客看菜单,服务员说:“您先看着菜单,点好了叫我”(回调函数)。这个时候这个服务员就可以抽身去服务其他的顾客。用这种模式的话,一个服务员就可以服务多位顾客,而且不需要等待 I/O ,只需要随时监听就行了,顾客点完后会主动叫服务员(执行回调函数).

单线程、非阻塞式 I/O 的优势就是性能强,一个人服务员就可以解决大量顾客。但是他的缺点也很明显,比如有一桌顾客和服务员又吵架了(线程崩了!),那这些顾客就都完了,因为所有人都在等这一个服务员。也就是说,如果线程崩掉了,那与这个服务器连接的所有用户都会崩溃.


但是,还有一个问题就是,如果有多个顾客都在叫你,该如何响应?肯定要有一定的规则,这就涉及到了Node的事件驱动。所以说,这三大特点,其实也是一个事,缺任何一个都不行。

声明:Jensonhui's blog|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 【Node.js】如何理解非阻塞I/O模式


Just do it.