Node.js中非阻塞IO和事件循环总结
我已经学习和使用Node.js两个月了,用express结合mongoose编写了一个web应用和一个RESTful web api。回看官网Node.js首页对Node.js的介绍:Node.js采用了事件驱动、无阻塞的I/O模型,使得它轻量级、高效。那么无阻塞I/O模型是什么意思呢?
无阻塞输入输出模型
首先,IO操作无疑是耗时的。当服务器收到大量请求时,为每个请求创建一个进程或线程也会增加额外的内存开销,并可能浪费更多的时间和资源。
由于Node.js是事件驱动的,所以使用事件循环来解决IO操作带来的瓶颈问题。在Node.js中,一个IO操作通常会携带一个回调函数,当IO操作完成并返回时调用,而主线程继续执行下面的代码。简单用一个例子来说明这个问题:
request('http://www.google.com ',函数(错误、响应、正文){ console.log(正文);});控制台. log('完成!');这段代码的意思是向‘http://www . Google.com’发送请求,当请求返回时,调用回调函数输出响应信息。由于Node.js的运行机制,这段代码会输出‘Done!’运行后立即显示在控制台上。然后在一段时间后输出响应信息。
事件循环事件循环。
接下来,我们将讨论事件循环的机制。首先,我们来谈谈调用,比如下面的代码:
函数A(arg,func){ var A=arg;func();console . log(' A ');}函数B(){ console . log(' B ');} A(0,B);代码执行后,函数A被推入调用框成为栈顶元素,开始执行A,执行过程中,函数B被推入调用框成为顶元素。执行完B后,B弹出调用框,A再次成为顶元素。执行完A后,A弹出调用框,调用框处于空闲状态。
Javascript运行时中有一个消息队列,消息与一个回调函数相关联。当事件被触发时,如果事件有相应的回调函数,消息将被添加到消息队列中。
回头看,什么是事件循环到结束循环?代码开始执行后,函数被推入调用框。以上面的例子为例,请求被推入调用框。这个函数将发出一个http请求(这个http请求将由Node.js的底层模块实现),并将请求完成的事件与一个回调函数相关联。该请求被弹出到呼叫框、控制台。当请求完成时,会触发完成事件,并将消息添加到消息队列中。消息队列首先检查呼叫箱是否空闲。如果呼叫箱没有空闲,会等到呼叫箱空闲,然后弹出消息队列的头。此时,执行与消息相关联的回调函数。
总结
以上总结了无阻塞模型和事件循环的概念。这个事件循环的机制并不是Node.js独有的,Node.js的代码是由单线程执行的。面对大量并发请求,它有什么优势?
上图是Node.js的架构图,Node.js的底层模块负责维护线程池。当发出IO请求时,node.js的底层模块会创建一个新的线程来处理该请求,然后将结果返回给上层。然后,当有多个请求时,Node.js的底层模块会使用尽可能少的线程来完成最多的任务,如果有空闲的线程,它会继续被用来做其他事情,这对于为每个请求打开一个新的进程或线程来说,无疑是“更聪明”和更高效的。
本文是学习Node.js的总结,如有问题和不足,请批评指正。
版权声明:Node.js中非阻塞IO和事件循环总结是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。