zlx362211854 / daily-study

每日一个知识点总结,以issue的形式体现
10 stars 6 forks source link

51.谈谈对 Node.js 异步 IO 机制的理解 #89

Open nanslee opened 5 years ago

goldEli commented 5 years ago

node.js 是单线程的,为了解决异步问题,引入了事件轮询。

事件轮询主要分两步:

  1. 异步任务执行完后,将回调放入事件队列中。
  2. 每当执行栈清空,事件队列的第一个回调将压入执行栈中执行。

这样就不会因为等待某个异步任务执行,从而阻塞执行栈的执行。

nanslee commented 5 years ago

异步 I/O 即非阻塞 I/O ,那么什么是阻塞 I/O,什么是非阻塞 IO 呢?

像传统的 Linux 就是阻塞 I/O,假设我们有一个 Shell 脚本是用来读文件的,那么每次读文件会先开启一个线程进行流程:开启一个读取流,读完后再关闭,再进行下一个文件读取,举个例子就像食堂打饭,你端着饭盒阿姨打好饭了你才走,下一个人才能打,而 Node.js 则采用异步非阻塞 I/O 机制来解决这个时间开销,举个例子就还是食堂打饭,但每个人提前把饭盒都给阿姨,阿姨只负责打饭就行了,我们排好队一个一个领就行了。

好了我们现在用通俗的话解释一下:异步非阻塞 I/O 是一种机制,由于 Node.js 是单线程的,所以当回调函数被执行的时候,事件循环是被暂停的,当涉及到I/O操作的时候,Node.js 会开一个独立的线程来进行异步 I/O 操作,操作结束以后将消息压入消息队列,类似浏览器事件循环。那么如果 在 while 循环中轮询等待执行的操作,会造成不必要的 CPU 运算的浪费,因为此时 I/O 操作未完成,read 函数拿不到结果,又该如何呢?

放心,Node.js 还有个机制是 I/O 多路复用,故名意思是在一个进程内同时执行多个 I/O 操作。本身也有一段进化的过程,这样一旦发现 I/O 操作完成就会返回的。