Node.js事件循环

fte*_*tes 35 events loops node.js

Node.js I/O事件是单线程还是多线程?

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

Wil*_*eer 83

事件循环

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

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

有几种方法可以对回调如何添加到事件循环进行基本操作.通常你不应该需要这些,但偶尔它们会很有用.

在任何时候都不会有两个真正的并行执行路径,因此所有操作本质上都是线程安全的.通常会有几个由事件循环管理的异步并发执行路径.

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

限制

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

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

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

阅读有关用例的更多信息

控制流

为了管理编写许多回调,您可能希望使用控制流库.我相信这是目前最流行的基于回调的库:

我使用了回调,它们几乎让我疯狂,我有更好的使用Promises的经验,bluebird是一个非常受欢迎且快速的承诺库:

我发现这是节点社区中一个非常敏感的话题(回调与承诺),所以无论如何,使用你认为最适合你个人的东西.一个好的控制流库也应该为您提供异步堆栈跟踪,这对于调试非常重要.

当事件循环中的最后一个回调完成它的执行路径并且不注册任何其他回调时,Node.js进程将结束.

这不是一个完整的解释,我建议你查看以下帖子,它是最新的:

我如何开始使用Node.js


ral*_*aul 22

来自Willem的回答:

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

我想开始用上面的引用来解释,这是我到处看到的节点js框架的常见误解之一.

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

nodejs的主要优点和优点是你永远不需要关心那些内部线程,他们将远离你的代码!通常在多线程环境中发生的所有讨厌的同步内容都将由nodejs框架抽象出来,您可以在更加程序员友好的环境中愉快地处理单个线程(主节点线程)(同时受益于多个线程的所有性能增强)线程).

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

  • 我是说事件循环运行单线程,而不是整个节点。我补充了我的答案,指出您不必专门处理应用程序代码中的线程。感谢反馈。 (2认同)