node.js - Node.js 什么时候阻塞?

标签 node.js multithreading asynchronous event-handling

我已经使用 Node.js 一段时间了,我才意识到它可能会阻塞。我就是想不通 Node.js 会阻塞的情况。

  • 因此,Node.js 是单线程的,因为 (i) Javascript 是 (ii) 避免所有多线程陷阱。
  • 尽管是单线程的,但要同时做很多事情,它 实现异步执行。所以,与数据库交谈(I/O 一般来说)是非阻塞的(因为它是异步的)。
  • 但是,所有传入的请求都要做一些工作(即与数据库交谈)和 该工作的所有结果必须返回给客户(即发送 一些数据)他们使用那个单线程。
  • Node.js 在单个线程中使用“事件循环”来获取所有 请求并将它们分配给非阻塞 I/O 任务。

因此,由于异步回调,I/O 任务是非阻塞的,但是单线程可能是阻塞的,因为它是同步的,并且事件循环可能会因为同时出现许多复杂的请求而堵塞?

  1. 我说得对吗?我的理解正确吗?我想我不会因为 herehere他们强调“Node 是单线程的 这意味着您的代码都不会并行运行”。那实际上是什么 是什么意思,它是如何使 Node 阻塞的?
  2. 因此,事件循环永远运行并始终搜索请求,或者 它在发现新请求后开始执行?
  3. Node 阻塞弱点是否使 Node 无法用于大型应用程序? 项目并使其最终只适用于微型网站和 小项目?

非常感谢。

最佳答案

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

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

然而, Node 中的几乎所有其他内容都发生在同一个单线程中。

现在具体解决您的问题:

  1. javascript 代码从单个线程运行这一事实不会造成 Node 阻塞。作为this answer解释说, Node 最重要的是(I/O)并发性而不是(代码)并行性。您可以利用内置的 cluster 并行运行 Node 代码例如在多核/CPU 系统上的模块,但 Node 的主要目标是能够同时处理大量 I/O,而无需为每个套接字/服务器/等分配一个线程。

  2. 有一篇很好、详细的文章 here描述了 Node 中的事件循环是如何工作的。

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

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

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

关于node.js - Node.js 什么时候阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36664123/

相关文章:

c# - 在 .NET 中如何最有效地利用多核进行短计算?

c - openmp 排序临界区

javascript - Promise .then() 链 : second . 然后在第一个之前运行? 0.0

javascript - JS 异步函数返回未定义,尽管在异步函数内调用它

python - IPython:在后台异步运行命令

javascript - 使用node sqlite3异步获取所有数据

javascript - React.js 和 webpack 2,需要一个解决方案

node.js - 为什么在 Node 中一定要使用 require 一步调用一个函数?

javascript - 如何更换2 |无缘无故?

c++ - 从另一个线程和类 C++ 更新 Winform 控件