nodejs是单线程的这一事实究竟意味着什么?



NodeJS网站是这样说的。重点是我的。

Node.js是一个基于Chrome的JavaScript运行时的平台,用于轻松构建快速,可扩展的网络应用程序。 Node.js使用事件驱动的非阻塞I/O模型,使其轻量级和高效,非常适合跨分布式设备运行的数据密集型实时应用程序。

即使我喜欢NodeJS,我也不明白为什么它比现有的技术(如Python, Java甚至PHP)更适合可扩展的应用程序。

据我所知,JavaScript运行时总是作为CPU中的单个线程运行。然而,IO可能使用底层内核方法,这些方法可能依赖于内核提供的线程池。

所以真正需要回答的问题是:

  1. 因为所有JS代码都将在单线程中运行,NodeJS不适合IO较少和大量计算的应用程序?
  2. 如果我正在使用nodejs编写一个web应用程序,并且有100个打开的连接,每个连接执行一个纯计算需要100ms,其中至少一个需要10s才能完成?
  3. 如果你的机器有10个核心,但如果你只运行一个nodeJS实例,你的其他9个cpu是活鸭子?

如果你也贴出其他技术在这种情况下是如何执行的,我将不胜感激。

我没有做过大量的节点,但我对此有一些看法。如果我说错了,请纠正。

因为所有JS代码都将在单线程中运行,所以NodeJS不适合IO较少和大量计算的应用程序?

是的。单线程意味着如果你在JS代码中处理大量数据,你会阻塞其他所有东西。这太糟糕了。但对于大多数web应用程序来说,这并不是典型的。

如果我正在使用nodejs编写一个web应用程序,并且有100个打开的连接,每个连接执行一个纯计算需要100毫秒,其中至少一个需要10秒才能完成?

是的。10秒的CPU时间。

如果你的机器有10个核心,但如果你只运行一个nodeJS实例,你的其他9个cpu是活鸭子?

我不确定。V8引擎可能有一些利用多核的优化,对程序员来说是透明的。但我对此表示怀疑。


问题是,大多数时候web应用程序不进行计算。如果你的应用设计得很好,一个请求就能很快得到响应。如果你需要获取东西(数据库,文件,远程服务),你不应该在处理下一个请求之前等待获取返回。

因此,由于I/O回调发生的时间,您可能在不同阶段同时在不同完成阶段有许多请求。即使一次只有一个请求在运行JS代码,该代码也应该非常快地完成它需要做的事情,退出运行循环,并等待下一个事件回调。

如果你的JS不能快速运行,那么这个模型确实会带来问题。正如您所注意到的,当CPU运行异常时,事情就会挂起。因此,不要构建一个节点web应用程序,它会在运行中进行大量密集的计算。

但是,您可以将事情重构为异步的。也许您有一个可以为您执行计算的独立节点脚本,并在计算完成时提供回调。然后,您的web应用程序可以将该脚本作为子进程启动,告诉它做一些事情,并在它完成时提供一个回调来运行。你现在有一种伪造的线程,以一种迂回的方式。


在几乎所有的web应用程序技术中,你都不希望在运行中进行复杂而紧张的计算。即使有合适的穿线,这也是一场失败的战斗。相反,你必须制定策略。在后台执行计算,或者在主web应用程序进程之外的cron作业中定期执行计算。

你指出的是理论上的缺陷,但在实践中,只有当你做得不对时,它才真正成为一个问题。

Node.js是单线程的。这意味着任何会阻塞主线程的事情都需要在主线程之外完成。

在实践中,这只是意味着使用回调来进行繁重的计算,就像您使用回调来处理I/o一样。

例如,下面是节点bcrypt的API
var bcrypt = require('bcrypt');
bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash("B4c0//", salt, function(err, hash) {
        // Store hash in your password DB.
    });
});

Mozilla Persona在生产中使用的。

最新更新