Node.js事件循环

Node.js I / O事件循环是单线程的还是multithreading的?

如果我有几个I / O进程,节点将它们放在外部事件循环中。 它们是按顺序处理(最快的)还是处理事件循环以同时处理它们(…以及在哪些限制中)?

事件循环

Node.js事件循环在单个线程下运行,这意味着您编写的应用程序代码将在单个线程上进行评估。 Nodejs本身通过libuv使用下面的许multithreading,但是在编写nodejs代码时,你永远不必处理这些线程。

涉及I / O呼叫的每个呼叫都需要您注册一个回叫。 这个调用也立即返回,这允许你并行地执行多个IO操作,而不需要在应用程序代码中使用线程。 一旦I / O操作完成,它的callback将被推送到事件循环中。 只要在执行之前在事件循环中推送的所有其他callback,它就会被执行。

有几种方法可以对如何将callback添加到事件循环中进行基本操作。 通常你不应该需要这些,但是时不时地他们可以是有用的。

  • setImmediate
  • process.nextTick

任何时候都不会有两条真正的并行执行path,所以所有的操作本质上都是线程安全的。 通常会有多个由事件循环pipe理的asynchronous并发执行path。

阅读关于事件循环的更多信息

限制

由于事件循环,节点不必为每个传入的tcp连接启动一个新的线程。 这允许节点同时服务数十万个请求 ,只要您不计算每个请求的前1000个质数。

这也意味着不要进行CPU密集型操作,因为这些操作会locking事件循环,并阻止其他asynchronous执行path的继续。 不使用所有I / O方法的sync变体也很重要,因为这些方法也会locking事件循环。

如果你想做CPU繁重的事情,你应该把它委派给一个不同的进程,可以更有效地执行CPU绑定操作,或者你可以把它写成一个本地添加的节点 。

阅读关于用例的更多信息

控制stream

为了pipe理写许多callback你可能会想要使用控制stream库。 我相信这是目前最stream行的基于callback的库:

我已经使用callback,他们几乎让我疯狂,我已经有了更好的使用承诺的经验,蓝鸟是一个非常受欢迎和快速的承诺库:

我发现这是节点社区中一个非常敏感的话题(callback与承诺),所以通过一切手段,使用你认为最适合你的方式。 一个好的控制stream库也应该给你asynchronous堆栈跟踪,这对于debugging非常重要。

当事件循环中的最后一个callback完成它的执行path并且没有注册任何其他的callback时,Node.js过程将结束。

这不是一个完整的解释,我build议你检查下面的线程,这是相当新的:

我如何开始使用Node.js

从威廉的回答:

Node.js事件循环在单个线程下运行。 每个I / O呼叫都要求您注册一个回叫。 每个I / O调用也会立即返回,这允许您在不使用线程的情况下并行执行多个IO操作。

我想用上面的这句话来解释一下,这是我所见到的各种js框架常见的误解之一。

Node.js不会神奇地处理所有那些只有一个线程的asynchronous调用,并且仍然保持该线程畅通。 它在内部使用谷歌的V8引擎和一个名为libuv(用c ++编写)的库,使它能够将一些潜在的asynchronous工作委派给其他工作者线程(类似于等待那里任何工作从主节点线程委派的线程池)。 然后,当那些线程完成它们的执行时,它们会调用它们的callback函数,这就是事件循环如何知道工作线程执行完成的事实。

nodejs的主要和优点是你永远不需要关心这些内部线程,他们将远离你的代码! 所有通常在multithreading环境中发生的令人讨厌的同步事件将被nodejs框架抽象出来,并且您可以在更多的程序员友好的环境中愉快地工作在单线程(主节点线程)上(同时受益于multithreading的所有性能增强线程)。

下面是一个很好的post,如果有人感兴趣: 什么时候使用线程池?