小结Node.js中非阻塞IO和事件循环

  学习和使用Node.js已经有两个月,使用express结合mongoose写了一个web应用和一套RESTful web api,回过头来看Node.js官网首页对Node.js的介绍:Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.那么其中的non-blocking I/O model 意味着什么呢?

非阻塞的IO模型

  首先,IO操作无疑是耗时的,当服务器端接收到大量请求时,为每一个请求创建进程或线程的同时,也增加了额外的内存开销,也可能浪费更多的时间资源。

  由于Node.js是事件驱动的,于是它使用了事件循环来解决IO操作带来的瓶颈问题。在Node.js中,一个IO操作通常会带有一个回调函数,当IO操作完成并返回时,就会调用这个回调函数,而主线程则继续执行接下来的代码。简单的用一个例子来说明这个问题:

request('http://www.google.com', function(error, response, body) {
   console.log(body);
});

console.log('Done!');

  这段代码的意思是向'http://www.google.com'发出请求,当请求返回这则调用回调函数输出响应信息。由于Node.js的运行机制,这段代码运行后,会立即在控制台输出'Done!',然后一段时间后再输出响应的信息。

事件循环 event loop

  接下来,来讨论下事件循环的机制。首先说说调用桟,比如有如下一段代码:

function A(arg, func){
  var a = arg;

  func();
  console.log('A');
}

function B(){
  console.log('B');
}

A(0, B);

  当代码执行后,函数A首先被推入调用桟中成为栈顶元素并开始执行A,在执行过程中函数B又被推入调用桟成为栈顶元素,在B执行完成后,B被弹出调用桟,A再次成为栈顶元素,在A执行完成后A被弹出调用桟,调用桟呈空闲状态。

  在Javascript运行时中存在一个消息队列,而消息和一个回调函数相关联,当一个事件被触发时,如果这个事件有相应的回调函数,则该消息就会被加入到消息队列中去。

  回过头来说事件循环到底循环的是什么,在代码开始执行后,函数被不断推入调用桟中,就拿上面的例子来讲,request被推入调用桟中,这个函数将进行一个http请求(这个http请求将交由Node.js的底层模块来实现)同时请求完成的事件和一个回调函数关联起来,request被弹出调用桟,console.log被推入调用桟开始执行。当请求完成时,完成事件被触发,一条消息被添加进消息队列中,消息队列首先会检查调用桟是否为空闲状态,如果调用桟并不空闲,则会一直等待到调用桟空闲状态后,将消息队列的头部弹出,此时与该消息相关联的回调函数被执行。

小结

  以上就无阻塞模型和事件循环在概念上进行了总结。而这个事件循环的机制并不仅仅是Node.js所独有的,并且Node.js的代码是单线程执行的,在面对大量并发请求的时候,又有着什么优势呢?

  上面这张图展示了Node.js的架构图,Node.js的底层有一个模块负责维护线程池,当一个IO请求发出的时候,Node.js的底层模块将新建一个线程来处理请求,完成后再将结果交还给上层。那么,当有多个请求的时候,Node.js的底层模块将利用尽可能少的线程来完成最多的任务,如果存在空闲的线程,它将继续被利用来做其他的事情,这对于前面说的针对每个请求开一个新的进程或线程而言,无疑“聪明”许多,也更加高效了。

  这篇文章是对学习Node.js的一个总结,其中若有问题和不足,欢迎批评指正。

(0)

相关推荐

  • Node.js 事件循环详解及实例

     Node.js  事件循环详解及实例 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现. Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数. Node.js 有多个内置的事件,我们可以

  • Node.js事件循环(Event Loop)和线程池详解

    Node的"事件循环"(Event Loop)是它能够处理大并发.高吞吐量的核心.这是最神奇的地方,据此Node.js基本上可以理解成"单线程",同时还允许在后台处理任意的操作.这篇文章将阐明事件循环是如何工作的,你也可以感受到它的神奇. 事件驱动编程 理解事件循环,首先要理解事件驱动编程(Event Driven Programming).它出现在1960年.如今,事件驱动编程在UI编程中大量使用.JavaScript的一个主要用途是与DOM交互,所以使用基于事件

  • 我的Node.js学习之路(三)--node.js作用、回调、同步和异步代码 以及事件循环

    一,node.js的作用, I/O的意义,(I/O是输入/输出的简写,如:键盘敲入文本,输入,屏幕上看到文本显示输出.鼠标移动,在屏幕上看到鼠标的移动.终端的输入,和看到的输出.等等)   node.js想解决的问题,(处理输入,输入,高并发 .如 在线游戏中可能会有上百万个游戏者,则有上百万的输入等等)(node.js适合的范畴:当应用程序需要在网络上发送和接收数据时Node.js最为适合.这可能是第三方的API,联网设备或者浏览器与服务器之间的实时通信)   并发的意义,(并发这个术语描述的

  • 深入理解Node.js 事件循环和回调函数

    本文详细的介绍了Node.js 事件循环和Node.js回调函数,废话不多说了,具体看下面把.  一.Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高.Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发.Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现.Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观

  • 深入浅析Node.js 事件循环

    Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. (来源于Javascript是单线程又是异步的,但是这种语言有个共同的特点:它们是 event-driven 的.驱动它们的 event 来自一个异构的平台.) Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现. Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件

  • 小结Node.js中非阻塞IO和事件循环

    学习和使用Node.js已经有两个月,使用express结合mongoose写了一个web应用和一套RESTful web api,回过头来看Node.js官网首页对Node.js的介绍:Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.那么其中的non-blocking I/O model 意味着什么呢? 非阻塞的IO模型 首先,IO操作无疑是耗时的,当服务器

  • node.js中对Event Loop事件循环的理解与应用实例分析

    本文实例讲述了node.js中对Event Loop事件循环的理解与应用.分享给大家供大家参考,具体如下: javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进入主线程,而是进入一个 "任务队列" 里,"任务队列" 通知主线程,该异步任务才会进入主线程执行. 任务的运行机制如下: 1.所有同步任务在主线程上执行,形成一个

  • Node.js用Socket.IO做聊天软件的实现示例

    目录 效果 index.html文件 index.js 实现方法 效果 index.html文件 该页面主要是渲染聊天界面 <!DOCTYPE html> <html> <head> <title>Socket.IO chat</title> <style> body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, &

  • Node.js net模块功能及事件监听用法分析

    本文实例讲述了Node.js net模块功能及事件监听用法.分享给大家供大家参考,具体如下: net模块 对比C语言的网络编程,Node.js有更加简便的开发模式与模块提供.它就是net模块 在需要使用的时候只需要require("net")就可以引入模块了. var net = require("net"); 服务端编程 引入模块的前提下: 1. 创建一个新的TCP或IPC服务 var server = net.createServer(function(clie

  • 浅谈Node 异步IO和事件循环

    前言 学习Node就绕不开异步IO, 异步IO又与事件循环息息相关, 而关于这一块一直没有仔细去了解整理过, 刚好最近在做项目的时候, 有了一些思考就记录了下来, 希望能尽量将这一块的知识整理清楚, 如有错误, 请指点轻喷~~ 一些概念  同步异步 & 阻塞非阻塞 查阅资料的时候, 发现很多人都对 异步和非阻塞 的概念有点混淆, 其实两者是完全不同的, 同步异步指的是 行为即两者之间的关系 , 而阻塞非阻塞指的是 状态即某一方 . 以前端请求为一个例子,下面的代码很多人都应该写过 $.ajax(

  • iOS + node.js使用Socket.IO框架进行实时通信示例

    Socket.IO是一个基于WebSocket的实时通信库,在主流平台都有很好的支持,此文主要是通过一个小例子来演示Socket.IO的使用. 基础环境搭建 新建一个文件夹(JS工程),创建一个package.json,复制以下内容并保存. { "name": "socket-chat-example", "version": "0.0.1", "description": "my first s

  • Node.js中HTTP模块与事件模块详解

    Node.js的http服务器 通过使用HTTP模块的低级API,Node.js允许我们创建服务器和客户端.刚开始学node的时候,我们都会遇到如下代码: 复制代码 代码如下: var http = require('http'); http.createServer(function (req,res) {     res.end('Hello World\n'); }).listen(3000,"127.0.0.1"); console.log("Server funni

  • 使用Node.js和Socket.IO扩展Django的实时处理功能

    今天,我们的目标是使用Django,Redis,和Socket.IO建立一个实时的聊天室.虽然几乎所有的Web应用程序都可以建立一个聊天室的.这篇文章将以较高的水平告诉你如何将基于REST的应用程序转换成一个实时的Web应用程序的.我会使用Django创建REST的部分,实际上自由地使用任何你舒服的语言/框架均可.接下来,让我们跳进代码,先列举我们所需要的部分. 组成: Django 1.4+ Redis 2.6.x (版本可选,但是建议使用) Redis-py 2.7.x (仅当你使用Redi

  • Vue与Node.js通过socket.io通信的示例代码

    一.Node中socket.io基础 1.是什么 Socket.IO类库,是在服务器和浏览器之间提供一个共享接口,其可以用于实现以下几种通信方式: HTML5中的WebSocket通信 Flash中使用的WebSocket通信 XHR轮询 JSONP轮询 Forever Iframe 在通信时,客户端与服务器端可以使用相同的API 2.怎么用 原理:创建Scoket.IO服务器,该服务器依赖于一个已经创建的HTTP服务器 服务器端引入 var http=require('http') var s

  • node.js基于socket.io快速实现一个实时通讯应用

    随着web技术的发展,使用场景和需求也越来越复杂,客户端不再满足于简单的请求得到状态的需求.实时通讯越来越多应用于各个领域. HTTP是最常用的客户端与服务端的通信技术,但是HTTP通信只能由客户端发起,无法及时获取服务端的数据改变.只能依靠定期轮询来获取最新的状态.时效性无法保证,同时更多的请求也会增加服务器的负担. WebSocket技术应运而生. WebSocket概念 不同于HTTP半双工协议,WebSocket是基于TCP 连接的全双工协议,支持客户端服务端双向通信. WebSocke

随机推荐