2

NodeJS 网站说以下内容。重点是我的。

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

尽管我喜欢 NodeJS,但我不明白为什么它比 Python、Java 甚至 PHP 等现有技术更适合可扩展的应用程序。

据我了解,JavaScript 运行时始终作为 CPU 中的单个线程运行。然而,IO 可能使用可能依赖于内核提供的线程池的底层内核方法。

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

  1. 因为所有 JS 代码都将在单线程中运行 NodeJS 不适合 IO 较少且计算量很大的应用程序?
  2. 如果我正在使用 nodejs 编写一个 Web 应用程序,并且有 100 个打开的连接,每个连接都执行需要 100 毫秒的纯计算,那么其中至少一个需要 10 秒才能完成?
  3. 如果您的机器有 10 个内核,但如果您只运行一个 nodeJS 实例,那么您的其他 9 个 CPU 就坐不住了?

如果您还发布其他技术在这些情况下如何执行即 NodeJS,我将不胜感激。

4

2 回答 2

3

我没有做过很多节点,但我对此有一些看法。如果我弄错了,请纠正,所以。

因为所有 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 应用程序技术中,您都不想在运行中进行复杂而密集的计算。即使有适当的线程,这也是一场失败的战斗。相反,你必须制定战略。在后台进行计算,或者在 cron 作业中定期进行计算,在主 Web 应用程序进程本身之外。

你指出的东西是理论上的缺陷,但在实践中,如果你做得不对,它真的只会成为一个问题。

于 2013-05-28T22:58:00.830 回答
2

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 在生产中使用的。 在这里查看他们的代码

于 2013-05-28T23:18:59.247 回答