用 NodeJS 充分利用多核 CPU 的资源

做者:Nick Major

翻译:疯狂的技术宅前端

原文:https://coderrocketfuel.com/a...node

未经容许严禁转载程序员

介绍面试

单个 Node.js 程序的实例仅在一个线程上运行,所以没法充分利用 CPU 的多核系统。有时你可能须要启动 Node.js 进程集群来利用本地计算机或生产服务器上的每一个 CPU 内核。express

在处理 API 或基于 ExpressJS 的HTTP服务器时,这个问题尤为重要。npm

幸运的是,Node.js 有一个名为 Cluster 的核心模块,它可以帮助咱们在 CPU 的全部核心上运行 Node.js 程序。segmentfault

在本文中,咱们将会用 Node.js 实现一个 ExpressJS HTTP 服务器,并在每一个 CPU 内核上建立一个惟一的实例。这样,因为每一个其CPU 核心实例都会提供可能的并发请求数,所以 HTTP 服务器的吞吐量将会大大增长。服务器

让咱们开始吧!微信

目录多线程

  • 建立 Express HTTP 服务器
  • 在多个 CPU 核心上运行服务器

建立 Express HTTP 服务器

咱们要作的第一件事是启动并运行 HTTP 服务器。若是你已经有了一个可用的 ExpressJS 服务器,则能够跳至下一部分:在多核 CPU 上运行服务器。

咱们将用 ExpressJS 来快速建立一个高效而简单的服务器。若是还没有安装 npm 软件包,则能够用如下命令进行安装:

$ npm install --save express

而后把下面的代码添加到要你的的 Node.js 文件中:

const express = require("express")
const PORT = process.env.PORT || 5000
const app = express()
app.listen(PORT, function () {
  console.log(`Express server listening on port ${PORT}`)
})

首先,咱们 require() 先前安装的 Express npm 软件包。

而后,咱们建立一个 PORT 变量,该变量能够是当前的 process.env.PORT 的值,也能够是 5000。而后用express() 方法建立一个 express 实例,并将其保存在 app 变量中。

最添加 app.listen() 函数,用于启动 Express 程序,并告诉它侦听咱们指定的 PORT。

经过命令行运行代码时,应该看到相似的内容输出到控制台:

Output:
Express server listening on port 5000

很好!如今咱们启动 Express HTTP 服务器。

在多个 CPU 核心上运行服务器

在本节中,咱们会把 Express 服务器运行在 CPU 的多个核心上!

为了帮助咱们实现这一目标,咱们将使用Node.js模块 OS 和 Cluster 。用 OS 模块来检测系统有多少个 CPU 核,用 Cluster 模块来建立多个子进程,咱们的 HTTP 服务器能够并行运行这些子进程。

因为这些是核心模块,所以不须要安装任何 npm 包,而且能够将它们 require()到咱们的代码中。

我将为你提供完整的代码,并在随后进行解释,所以,若是你看得一头雾水,也没有关系。

这是完整的代码:

const express = require("express")
const os = require("os")
const cluster = require("cluster")

const PORT = process.env.PORT || 5000

const clusterWorkerSize = os.cpus().length

if (clusterWorkerSize > 1) {
  if (cluster.isMaster) {
    for (let i=0; i < clusterWorkerSize; i++) {
      cluster.fork()
    }
    cluster.on("exit", function(worker) {
      console.log("Worker", worker.id, " has exitted.")
    })
  } else {
    const app = express()
    app.listen(PORT, function () {
      console.log(`Express server listening on port ${PORT} and worker ${process.pid}`)
    })
  }
} else {
  const app = express()
  app.listen(PORT, function () {
    console.log(`Express server listening on port ${PORT} with the single worker ${process.pid}`)
  })
}

代码中作了不少事情,因此让咱们解释它的每个部分。

首先是 require() express 包以及 Node.js 的两个核心模块 os 和 cluster。

接下来,建立一个 PORT 变量,并为其分配当前 process.env.PORT 编号或 5000 的值。咱们稍后将在启动时用到它。

而后,咱们建立一个名为 clusterWorkerSize 的变量来表示系统的 CPU 数量。能够用 os.cpus().length方法得到这个数字。 查看 Node.js 文档来获取有关 os.cpus() 方法的更多信息。

咱们建立一个了 if...else语句,用 clusterWorkerSize 值检查 CPU 是否有多个核。若是 CPU 数量大于 1,咱们就继续建立集群。可是若是运行代码的计算机上只有一个 CPU 核心,则以本教程第一步中的方式启动 Express 程序。

假设咱们的机器有多个 CPU 核心,那么就要建立另外一个 if...else 语句,检查该语句是否为集群中已运行的第一个进程。用 cluster.isMaster() 方法检查是否返回 true 或 false。

若是是第一个运行的进程,咱们将用 cluster.fork() 为计算机上的每一个 CPU 核产生一个新的工做进程。咱们还添加了一个事件侦听器,该侦听器将在工做进程退出时输出一条消息,以便咱们知道什么时候出现问题或意外。

值得注意的是,主进程用于侦听 HTTP 服务器的端口,并在工做进程之间平衡全部请求的负载。

产生全部工做进程后,咱们将在建立的每一个工做进程上建立一个程序的新实例。若是你的计算机有 2 个 CPU 核,则将会建立该程序的 2 个实例。

运行程序时,应该可以在控制台上看到如下内容:

Output:

Express server listening on port 5000 and worker 10801
Express server listening on port 5000 and worker 10802
Express server listening on port 5000 and worker 10803
Express server listening on port 5000 and worker 10804

输出将根据 CPU 核的数量而有所不一样。

如今你有了一个可以在多核 CPU 上运行的 HTTP 服务器!

结论

cluster 模块使咱们可以轻松建立子进程,从而为 Node.js 提供了使用 CPU 所提供的所有功能所急需的功能。而且它还在后台为在主进程和工做进程之间进行通讯作了大量工做。

在读完本文以后,你如今应该知道该如何使用这个模块在多个 CPU 核心上运行 Express HTTP 服务器。有了这些知识,你将可以更好地管理和扩展你的应用。


本文首发微信公众号:前端先锋

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章


欢迎继续阅读本专栏其它高赞文章:


相关文章
相关标签/搜索