关于Node.js的第一个基本概念是I/O操作开销是巨大的:

所以,当前变成技术中最大的浪费来自于等待I/O操作的完成。有几种方法可以解决性能的影响:

  • 同步方式:按次序一个一个的处理请求。利:简单;弊:任何一个请求都可以阻塞其他所有请求。
  • 开启新进程:每个请求都开启一个新进程。利:简单;弊:大量的链接意味着大量的进程。
  • 开启新线程:每个请求都开启一个新线程。利:简单,而且跟进程比,对系统内核更加友好,因为线程比进程轻的多;弊:不是所有的机器都支持线程,而且对于要处理共享资源的情况,多线程编程会很快变得太过于复杂。

第二个基本概念是每个连接都创建一个新线程是很消耗内存的(例如:你可以对比Nginx回想一下Apache内存耗尽的情景)。

Apache是多线程的:它为每个请求开启一个新的线程(或者是进程,这取决于你的配置),当并发连接增多时,你可以看看它是怎么一点一点耗尽内存的。Nginx和Node.js不是多线程的,因为线程的消耗太“重”了。它们两个是单线程、基于事件的,这就把处理众多连接所产生的线程/进程消耗给消除了。

Node.js中你的代码运行在单线程之中

确实只有一个线程:你不能并行执行任何代码,比如:下面的“sleep”将会阻塞sever1秒钟:

while(new Date().getTime() < now + 1000) {
// do nothing
}

当这段代码运行时,Node.js不会响应客户端任何请求,因为只有一个线程来运行你的代码,另外,如果你执行cpu密集的任务,比如重设图像的大小,它也会阻塞所有请求。

……然而,除了你的代码,其它的一切都是并行执行的

单线程没法让代码并行执行。但是所有I/O操作都是事件驱动、并行的,所以下面的代码不会阻塞server:

c.query(
'SELECT SLEEP(20);',
function (err, results, fields) {
if (err) {
throw err;
}
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<html><head><title>Hello</title></head><body><h1>Return from async DB query</h1></body></html>');
c.end();
}
);

如果你在一次请求中执行这些,当数据库sleep时,其他请求也会立即被处理。

为什么异步比较好?什么时候我们应该从同步转移到异步/并行执行呢?

同步执行也不错,因为它简便了我们敲代码。但在使用异步时,你不必关心后端是怎么处理的。而且,在I/O操作时不会阻止其他请求,同时无需承担每个请求所产生的线程/进程的成本。

I/O操作时使用异步处理很好,因为I/O操作的成本比单纯执行代码要高的多,我们应该在等待I/O时做其它更有意义的工作。

Event loop是指处理外部事件,并把外部事件转换为回调来进行调用的实体(晦涩难懂!!原文:an entity that handles and processes external events and converts them into callback invocations).所以,I/O调用的同时,server就可以去处理另一个请求。在一次I/O调用中,你的代码保存回调函数并把控制权交回到node.js运行时。当数据加载完毕可以访问时,就可以执行回调函数了。

当然,在后端有很多数据库接入和处理的进程。但是,这些都不需要通过你的代码直接实现,你也就不必了解后台I/O之间的相互作用关系。和Apache相比,省去了很多线程消耗,因为不是每个链接都需要新线程,仅那些需要并行运行的才需要新线程。

不只是I/O调用,Node.js期望所有的请求都能快速的响应,比如CPU密集的工作应该分离到其他进程,你可以使用事件和他交互。

内部实现

在内部,Node.js依赖libev来提供event loop,使用线程池来提供异步I/O。

Node.js之 EventLoop 理解(转)的更多相关文章

  1. NODE.JS exports require理解

    node.js exports 的作用是什么? 因为A.js文件想访问B.js文件中的类或函数,是不能直接访问的.为了解决这个问题 node.js 产生了 exports ,exports 实际可以理 ...

  2. node.js module初步理解

    在开发一个复杂的应用程序的时候,我们需要把各个功能拆分.封装到不同的文件,在需要的时候引用该文件.没人会写一个几万行代码的文件,这样在可读性.复用性和维护性上都很差,几乎所有的编程语言都有自己的模块组 ...

  3. Node.js 的初步理解

    Node.js 是一个采用C++语言编写的后端的 Javascript 的运行环境, 它使用了 google 的 V8虚拟机来解释和执行代码.Node.js 的有许多有用的内置的模块,比如 http, ...

  4. node.js module初步理解-(转载)

    在开发一个复杂的应用程序的时候,我们需要把各个功能拆分.封装到不同的文件,在需要的时候引用该文件.没人会写一个几万行代码的文件,这样在可读性.复用性和维护性上都很差,几乎所有的编程语言都有自己的模块组 ...

  5. Node.js学习(第一章:Node.js安装和模块化理解)

    Node.js安装和简单使用 安装方法 简单的安装方式是直接官网下载,然后本地安装即可.官网地址:nodejs.org Windows系统下,选择和系统版本匹配的.msi后缀的安装文件.Mac OS ...

  6. 深入理解Node.js基于事件驱动的回调

    回调和异步调用的关系 首先明确一点,回调并非是异步调用,回调是一种解决异步函数执行结果的处理方法.在异步调用,如果我们希望将执行的结果返回并且处理时,可以通过回调的方法解决.为了能够更好的区分回调和异 ...

  7. 《Node.js开发指南》的少许坑儿~

    由于express升级到3.0,造成这本书看起来more and more蛋疼.记录少许坑儿,方便后来人. 一.node.js在windows下的安装 书中在两处介绍了两种方式,其实现在的node.j ...

  8. Node.js : 我只需要一个店小二

    刚刚开始接触Node.js时, google了很多文章,但发现大部分都是泛泛的介绍安装,配置,以及介绍几个小例子 有一种雾里观花的感觉,所以非常困惑,不知道Node.js到底解决了什么问题,它的优势到 ...

  9. 10+ 最佳的 Node.js 教程和实例

    如果你正在找Node.js的学习资料及指南,那么请继续(阅读),我们的教程将会覆盖即时聊天应用.API服务编写.投票问卷应用.人物投票APP.社交授权. Node.js on Raspberry Pi ...

随机推荐

  1. go语言可变参数的坑

    0x00 前提 对可变参数不了解的同学,可以先看这篇文章可变参数终极指南 0x01 第一个坑 不能通过空接口类型向可变参数传递一个普通的切片 ,需要将普通切片转换为空接口切片 0x02 第二个坑 可变 ...

  2. regsvr32.exe是什么东西

    Regsvr32命令修复系统故障实例使用过activex的人都知道,activex不注册是不能够被系统识别和使用的,一般安装程序都会自动地把它所使用的activex控件注册,但如果你拿到的一个控件需要 ...

  3. 腾讯云安装Hadoop遇到的问题

    1.能正常访问bincoding.cn:50030,不能连接到9000端口 Call to bincoding.cn/123.206.212.115:9000 failed on connection ...

  4. TCP粘包, UDP丢包, nagle算法

    一.TCP粘包 1. 什么时候考虑粘包 如果利用tcp每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题(因为只有一种包结构,类似于http协议,UDP不会出 ...

  5. Android(我还是个菜鸟)——UI-开源框架ImageLoader的完美例子

    开源框架ImageLoader 可在文件里面找——Desktop.zip(原文件为jar格式) 使用这个框架的好处: 让图片能在异步加载更加流畅,可以显示大量图片,在拖动ListView的时候不会出现 ...

  6. keras系列︱迁移学习:利用InceptionV3进行fine-tuning及预测、完美案例(五)

    引自:http://blog.csdn.net/sinat_26917383/article/details/72982230 之前在博客<keras系列︱图像多分类训练与利用bottlenec ...

  7. Mac下配置Apache Httpd的Https/SSL

    Mac下配置Apache Httpd的Https/SSL httpd版本: httpd-2.4.17 jdk版本: jdk1.8.0_65 参考来源: Mac下安装Apache Httpd Mac O ...

  8. 如何让其他机器访问你的oracle数据库

    修改listen.ora SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = CLRExtProc) (ORACLE_HOME = E:\a ...

  9. Hibernate注解方式一对多自关联关系映射

    MySQL版数据库表结构   DROP TABLE IF EXISTS SYS_DICT_ITEM; CREATE TABLE SYS_DICT_ITEM( ITEM_CODE ) NOT NULL, ...

  10. TiKV 源码解析系列 - Raft 的优化

    本系列文章主要面向 TiKV 社区开发者,重点介绍 TiKV 的系统架构,源码结构,流程解析.目的是使得开发者阅读之后,能对 TiKV 项目有一个初步了解,更好的参与进入 TiKV 的开发中.本文是本 ...