为什么每个核心 运行 一个 Node.js 进程?

Why run one Node.js process per core?

根据 https://nodejs.org/api/cluster.html#cluster_cluster,应该 运行 与机器上的内核数量相同的 Node.js 进程并行。 这背后的假设原因是 Node.js 是单线程的。

然而,这是真的吗?当然 JavaScript 代码和事件循环 运行 在一个线程上,但 Node 也有一个工作线程池。此池中的默认线程数为 4。那么为什么 运行 每个核心一个节点进程有意义?

This article对[=19=的线程机制进行了扩展回顾,值得一读。

简而言之,要点很简单 node.js 只有少数函数调用使用线程池(DNS 和 FS 调用)。您的调用主要是 运行 事件循环 。因此,例如,如果您编写了一个 Web 应用程序,每个请求同步花费 100 毫秒,那么您将绑定到 10req/s。不会涉及线程池。而在多核系统上增加吞吐量就是使用其他内核。

然后是异步或者回调函数。虽然它确实给你一种并行化的感觉,但真正发生的是它等待异步代码在后台完成,以便事件循环可以在另一个函数调用上工作。之后,回调代码仍然要在事件循环中运行,因此您编写的所有代码仍然在唯一一个事件循环中运行,因此无法利用多核系统' 电源。

上述document明确指出Node是单线程的:

A single instance of Node.js runs in a single thread. To take advantage of multi-core systems, the user will sometimes want to launch a cluster of Node.js processes to handle the load.

这样 Node 进程只有一个线程,除非使用 child_processcluster、本机附加组件或使用 [=12 的 several built-in modules 等各自的 API 创建新线程=] 跑步池:

Asynchronous system APIs are used by Node.js whenever possible, but where they do not exist, libuv's threadpool is used to create asynchronous node APIs based on synchronous system APIs. Node.js APIs that use the threadpool are:

all fs APIs, other than the file watcher APIs and those that are explicitly synchronous

crypto.pbkdf2()

crypto.randomBytes(), unless it is used without a callback

crypto.randomFill()

dns.lookup()

all zlib APIs, other than those that are explicitly synchronous

单线程使用1个CPU核,为了最大限度的利用可用资源,利用多核CPU,应该有多个线程,核数作为经验法则。

如果集群进程占用 100% CPU 并且已知有其他线程或外部进程(数据库服务)会与集群进程争夺 CPU 个核心,则集群进程的数量可以减少。