用 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 服務器。有了這些知識,你將可以更好地管理和擴展你的應用。


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章


歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索