Node.js何时阻止?

sle*_*vin 8 multithreading asynchronous event-handling node.js

我已经使用了Node.js一段时间了,我才意识到它可以阻塞.我无法将我的大脑包裹在Node.js阻塞的条件下.

  • 因此,Node.js是单线程的,因为(i)Javascript是和(ii)避免所有多线程陷阱.
  • 尽管是单线程的,但是要一次完成很多事情,它实现了异步执行.因此,与DB(一般的I/O)交谈是非阻塞的(因为它是异步的).
  • 但是,所有进行某些工作的传入请求(即与DB交谈)以及必须返回客户端的所有工作结果(即发送一些数据)他们使用该单个线程.
  • Node.js使用单个线程内的"事件循环"来获取所有请求并将它们分配给非阻塞I/O任务.

因此,由于异步回调,I/O任务是非阻塞的,但是单个线程可能是阻塞的,因为它是同步的,因为事件循环可能被卡住,因为很多复杂的请求同时出现?

  1. 我是对的,我理解正确吗?我想我不会,因为 这里这里,他们强调的是"节点是单线程的,这意味着没有你的代码的并行运行".这究竟意味着什么以及它如何阻止节点?
  2. 那么,事件循环会永远运行并始终搜索请求,或者在发现新请求后开始执行?
  3. 节点阻塞弱点是否会使Node对大型项目无用,并使其最终仅适用于微型站点和小型项目?

非常感谢.

msc*_*dex 8

首先,要明确:node.js作为一个整体不是单线程的.Node通过libuv确实有一个线程池,它用于执行某些任务,这些任务目前无法从大多数平台上的单个线程(例如文件I/O)有效地执行,或者它们本身就是计算密集型的(例如zlib).应该注意的是,大多数crypto模块(其本身也是计算密集型)当前没有异步/非阻塞接口(除了crypto.randomBytes()).

v8还利用多个线程来执行垃圾收集,函数优化等操作.

但是,节点中的其他所有内容确实发生在同一个单线程中.

现在具体解决您的问题:

  1. javascript代码从单个线程运行的事实不会使节点阻塞.正如这个答案所解释的那样,node最重要的是(I/O)并发而不是(代码)并行.您可以通过利用内置cluster模块并行运行节点代码,例如在多核/ CPU系统上,但节点的主要目标是能够同时处理大量I/O而无需为每个插槽/服务器专用一个线程/等等.

  2. 这是一个很好的,详细的书面记录这里描述的节点事件循环是如何工作的.

  3. 如前所述,Node的主要目标是非常好地处理I/O,这适用于Web应用程序和任何类型的网络程序的大多数用例.

    如果您的脚本受CPU约束(例如,您正在计算pi或转码音频/视频),那么最好将该工作委托给节点中的子进程(例如,调用ffmpeg转码而不是在javascript或同步中进行转码)在节点的主线程上的c ++节点插件中).如果您没有同时执行任何其他操作(例如处理HTTP请求),您可以在进程中阻止这些操作.有许多人将以这种方式使用节点来执行各种实用程序任务,其中I/O并发性并不重要.其中一个示例可能是执行js和css文件的缩小,linting和/或捆绑的脚本,或者是从大量图像集创建缩略图的脚本.

    但是,如果您的脚本改为创建TCP或HTTP服务器,例如从数据库中提取信息,对其进行格式化并将其发送回用户,那么节点将擅长这样做,因为在此过程中花费了大部分时间只是等待套接字/ HTTP客户端发送(更多)数据并等待数据库回复查询结果.