多核处理器上的 Node Js

Van*_*ula 4 windows google-chrome v8 processor node.js

首先,我有一种直觉,这是一个完全完整的问题,但无论如何请听我说完。我在想,如果 Node Js 是一个单线程应用程序,那么我们是否可以在同一台机器上的不同端口上运行它的多个实例。假设我有 8 个线程处理器,这是否意味着我可以运行 8 个节点实例而不会影响性能。如果我安装了足够的内存,然后我可以为这 8 个实例进行负载平衡

jmr*_*mrk 9

(此处为 V8 开发人员。)

是的,一般来说,在同一台机器上运行多个 Node 实例可以增加完成的工作总量。这类似于拥有多个 Chrome 选项卡,每个选项卡都可以执行一些单线程 JavaScript 工作。

也就是说,它很可能不像“8 线程处理器上的 8 个实例提供 8 倍的总吞吐量”那么简单,原因如下:

(1) 如果您实际上是指“8 个线程”,即 4 个内核 + 超线程,那么从 4 个进程到 8 个进程可能会带来 20-40% 的改进(取决于硬件架构和特定工作负载),而不是 2 倍。

(2) V8 确实使用多个线程用于内部目的(主要是编译和垃圾收集),这也是单个 Node 实例可能(取决于工作负载)使用多个 CPU 内核/线程的原因之一。

(3) 另一个原因是虽然 JavaScript 是单线程的,但 Node 不仅仅执行 JavaScript 的单线程。后台发生的各种事情(准备就绪时会触发 JS 回调)也需要 CPU 资源。

(4) 最后,CPU 不一定是你的瓶颈。如果您的服务器性能受到网络或磁盘等因素的限制,那么生成更多实例将无济于事;相反,它可能会使事情变得更糟。

长话短说:尝试并没有什么坏处。第一步,在一个实例上运行一个典型的工作负载,并查看当前的系统负载(CPU、内存、网络、磁盘)。如果他们具有足够的闲置产能,尝试将两个实例,措施是否增加整体吞吐量,并检查系统的负荷试。然后继续添加实例,直到您注意到它不再有帮助。


Mes*_*San 9

除了@jmrk提供的出色答案之外,我还想对您问题的“不同端口”部分发表评论。

当涉及到多进程时,nodejs 最伟大的事情之一就是集群模块。您可以运行 1 个进程并对其进行多次分叉,并且可以使它们全部侦听同一端口。因此,例如,您不必使用 Nginx 来管理所有端口。

如果您想部署到可能具有不同核心数量的计算机集群,您可以通过将操作系统模块引入游戏来动态地完成此操作。

const cluster = require('cluster')

if (cluster.isMaster) {
  // Creates the Forks
  process.title = 'my-node-app-master'
  const { length: numberOfProcs } = require('os').cpus()
  for (let i = 0; i < numberOfProcs; i++) {
    cluster.fork()
  }

  // and here you can fork again when one of the forks dies
  cluster.on('exit', (worker, code, signal) => {
    console.error(`worker ${worker.process.pid} died (${signal || code}). restarting it in a sec`)
    setTimeout(() => cluster.fork(), 1000)
  })
} else {
  // run your server
  const http = require('http')
  process.title = 'my-node-app-fork'

  http.Server((req, res) => {
    res.writeHead(200)
    res.end(`hello world from pid ${process.pid}\n`)
  }).listen(8000)
}
Run Code Online (Sandbox Code Playgroud)

process.title将有助于检查过程。我在我的机器上运行该代码我得到了:

$ ps aux | grep node-app
daniel    8062  1.1  0.1 550008 31380 pts/1    Sl+  12:27   0:00 my-node-app-master
daniel    8069  0.5  0.1 549168 30476 pts/1    Sl+  12:27   0:00 my-node-app-fork
daniel    8070  0.3  0.1 549176 30644 pts/1    Sl+  12:27   0:00 my-node-app-fork
daniel    8077  0.5  0.1 549168 30376 pts/1    Sl+  12:27   0:00 my-node-app-fork
...
daniel    8157  0.3  0.1 549168 30668 pts/1    Sl+  12:27   0:00 my-node-app-fork
daniel    8194  0.0  0.0   9028  2468 pts/2    R+   12:28   0:00 grep --color=auto node-app
Run Code Online (Sandbox Code Playgroud)

然后提出几个要求:

$ curl http://localhost:8000
hello world from pid 8069
$ curl http://localhost:8000
hello world from pid 8070
$ curl http://localhost:8000
hello world from pid 8077
Run Code Online (Sandbox Code Playgroud)

当你杀死一个子进程时

$ kill -9 8077
Run Code Online (Sandbox Code Playgroud)

日志将显示

worker 8077 died (SIGKILL). restarting it in a sec
Run Code Online (Sandbox Code Playgroud)

我知道它与您的主要问题没有直接关系,但它仍然相关,我认为人们可以充分利用这一点。