目錄
Node.js集群模塊:它是做什麼的以及如何工作
如何在Node.js應用程序中使用集群模塊
如何開發高度可擴展的Express服務器
性能比較
主進程和工作進程之間的通信
零停機時間
使用Node.js集群的主要優勢是什麼?
Node.js集群是如何工作的?
如何創建一個Node.js集群?
如何處理Node.js集群中的工作進程崩潰?
我可以將Node.js集群與Express.js一起使用嗎?
Node.js集群的局限性是什麼?
如何在Node.js集群中負載均衡請求?
我可以在生產環境中使用Node.js集群嗎?
如何調試Node.js集群?
我可以將Node.js集群與其他Node.js模塊一起使用嗎?
首頁 web前端 js教程 如何創建一個node.js群集以加速您的應用

如何創建一個node.js群集以加速您的應用

Feb 19, 2025 pm 12:01 PM

How to Create a Node.js Cluster for Speeding Up Your Apps

核心要點

  • Node.js憑藉其事件驅動架構和非阻塞I/O API,成為處理高流量網站的熱門服務器端運行環境,允許異步請求處理。
  • Node.js的可擴展性是其被大型公司採用的關鍵特性。儘管默認情況下在單線程中運行並具有內存限制,但Node.js可以通過集群模塊將單個進程拆分為多個進程或工作進程來擴展應用程序。
  • Node.js集群模塊通過多次執行相同的Node.js進程來工作。它允許識別主進程並創建工作進程,這些工作進程可以共享服務器句柄並與父Node進程通信。
  • Node.js應用程序可以使用集群模塊進行並行化,允許多個進程同時運行。這提高了系統的效率,改善了應用程序性能,並增強了可靠性和正常運行時間。
  • 雖然Node.js集群模塊主要推薦用於Web服務器,但在仔細考慮工作進程之間的任務分配以及工作進程和主進程之間的有效通信的情況下,也可以將其用於其他應用程式.

Node.js作為服務器端運行環境越來越受歡迎,尤其是在高流量網站方面,統計數據也證明了這一點。此外,眾多框架的可用性使其成為快速原型設計的良好環境。 Node.js具有事件驅動的架構,利用非阻塞I/O API允許異步處理請求。 Node.js的一個重要且經常被忽視的特性是其可擴展性。事實上,這是某些大型公司在其平台中集成Node.js(例如Microsoft、Yahoo、Uber和Walmart)甚至將其服務器端操作完全遷移到Node.js(例如PayPal、eBay和Groupon)的主要原因。每個Node.js進程都在單個線程中運行,默認情況下,32位系統的內存限制為512MB,64位系統的內存限制為1GB。儘管可以在32位系統上將內存限制提高到約1GB,在64位系統上提高到約1.7GB,但內存和處理能力仍然可能成為各種進程的瓶頸。 Node.js為擴展應用程序提供的優雅解決方案是將單個進程拆分為多個進程或Node.js術語中的工作進程。這可以通過集群模塊實現。集群模塊允許您創建子進程(工作進程),這些子進程與主Node進程(主進程)共享所有服務器端口。在本文中,您將了解如何創建Node.js集群以加快應用程序的速度。

Node.js集群模塊:它是做什麼的以及如何工作

集群是在父Node進程下運行的類似工作進程的池。工作進程使用child_processes模塊的fork()方法生成。這意味著工作進程可以共享服務器句柄並使用IPC(進程間通信)與父Node進程通信。主進程負責啟動和控制工作進程。您可以在主進程中創建任意數量的工作進程。此外,請記住,默認情況下,傳入連接在工作進程之間以輪詢方式分配(Windows除外)。實際上,還有另一種分配傳入連接的方法,這裡我不會討論,它將分配交給操作系統(Windows中的默認設置)。 Node.js文檔建議使用默認的輪詢樣式作為調度策略。儘管從理論上講,使用集群模塊聽起來很複雜,但其實現非常簡單。要開始使用它,您必須將其包含在您的Node.js應用程序中:

var cluster = require('cluster');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

集群模塊多次執行相同的Node.js進程。因此,您需要做的第一件事是確定哪一部分代碼用於主進程,哪一部分代碼用於工作進程。集群模塊允許您如下識別主進程:

if(cluster.isMaster) { ... }
登入後複製
登入後複製
登入後複製

主進程是您啟動的進程,它又會初始化工作進程。要在主進程中啟動工作進程,我們將使用fork()方法:

cluster.fork();
登入後複製
登入後複製
登入後複製

此方法返回一個worker對象,其中包含有關已派生的worker的一些方法和屬性。我們將在下一節中看到一些示例。集群模塊包含多個事件。與工作進程啟動和終止時刻相關的兩個常見事件是online和exit事件。當工作進程派生並發送online消息時,會發出online事件。當工作進程死亡時,會發出exit事件。稍後,我們將了解如何使用這兩個事件來控制工作進程的生命週期。現在,讓我們將到目前為止看到的所有內容放在一起,並展示一個完整的可運行示例。

示例

本節包含兩個示例。第一個示例是一個簡單的應用程序,顯示如何在Node.js應用程序中使用集群模塊。第二個示例是一個利用Node.js集群模塊的Express服務器,它是我通常在大規模項目中使用的生產代碼的一部分。這兩個示例都可以從GitHub下載。

如何在Node.js應用程序中使用集群模塊

在這個第一個示例中,我們設置了一個簡單的服務器,它使用包含處理請求的工作進程ID的消息來響應所有傳入請求。主進程派生四個工作進程。在每個工作進程中,我們開始監聽端口8000以接收傳入請求。實現我剛才描述的內容的代碼如下所示:

var cluster = require('cluster');
var http = require('http');
var numCPUs = 4;

if (cluster.isMaster) {
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end('process ' + process.pid + ' says hello!');
    }).listen(8000);
}
登入後複製
登入後複製

您可以通過啟動服務器(運行命令node simple.js)並訪問URL https://www.php.cn/link/7d2d180c45c41870f36e747816456190

如何開發高度可擴展的Express服務器

Express是Node.js最流行的Web應用程序框架之一(如果不是最流行的話)。在本網站上,我們已經多次介紹過它。如果您有興趣了解更多信息,我建議您閱讀文章《使用Express 4創建RESTful API》和《構建Node.js驅動的聊天室Web應用程序:Express和Azure》。第二個示例顯示瞭如何開發高度可擴展的Express服務器。它還演示瞭如何遷移單個進程服務器以利用少量代碼的集群模塊。

var cluster = require('cluster');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

此示例的第一個補充是使用Node.js os模塊獲取CPU內核的數量。 os模塊包含一個cpus()函數,它返回一個CPU內核數組。使用這種方法,我們可以根據服務器規格動態確定要派生的工作進程數量,以最大限度地利用資源。第二個更重要的補充是處理工作進程的死亡。當工作進程死亡時,集群模塊會發出exit事件。可以通過偵聽該事件並在發出該事件時執行回調函數來處理它。您可以通過編寫類似cluster.on('exit', callback);的語句來做到這一點。在回調函數中,我們派生一個新的工作進程以保持預期的工作進程數量。這允許我們保持應用程序運行,即使有一些未處理的異常。在這個示例中,我還為online事件設置了一個偵聽器,每當派生工作進程並準備好接收傳入請求時,就會發出該事件。這可用於日誌記錄或其他操作。

性能比較

有幾種工具可以對API進行基準測試,但這裡我使用Apache Benchmark工具來分析使用集群模塊如何影響應用程序的性能。為了設置測試,我開發了一個Express服務器,它有一個路由和一個用於該路由的回調函數。在回調函數中,執行一個虛擬操作,然後返回一條簡短的消息。服務器有兩個版本:一個沒有工作進程,其中所有操作都在主進程中發生,另一個有8個工作進程(因為我的機器有8個內核)。下表顯示了合併集群模塊如何增加每秒處理的請求數。

并发连接 1 2 4 8 16
单进程 654 711 783 776 754
8个工作进程 594 1198 2110 3010 3024

(每秒處理的請求數)

高級操作

雖然使用集群模塊相對簡單,但您可以使用工作進程執行其他操作。例如,您可以使用集群模塊實現應用程序的(幾乎!)零停機時間。我們過一會兒將了解如何執行其中一些操作。

主進程和工作進程之間的通信

有時,您可能需要從主進程向工作進程發送消息以分配任務或執行其他操作。作為回報,工作進程可能需要通知主進程任務已完成。要偵聽消息,應在主進程和工作進程中都設置message事件的事件偵聽器:

var cluster = require('cluster');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

worker對像是fork()方法返回的引用。要在工作進程中偵聽來自主進程的消息:

if(cluster.isMaster) { ... }
登入後複製
登入後複製
登入後複製

消息可以是字符串或JSON對象。要向特定工作進程發送消息,您可以編寫如下所示的代碼:

cluster.fork();
登入後複製
登入後複製
登入後複製

類似地,要向主進程發送消息,您可以編寫:

var cluster = require('cluster');
var http = require('http');
var numCPUs = 4;

if (cluster.isMaster) {
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end('process ' + process.pid + ' says hello!');
    }).listen(8000);
}
登入後複製
登入後複製

在Node.js中,消息是通用的,沒有特定類型。因此,最好將消息作為包含有關消息類型、發送者和內容本身的一些信息的JSON對象發送。例如:

var cluster = require('cluster');

if(cluster.isMaster) {
    var numWorkers = require('os').cpus().length;

    console.log('Master cluster setting up ' + numWorkers + ' workers...');

    for(var i = 0; i < numWorkers; i++) {
        cluster.fork();
    }

    cluster.on('online', function(worker) {
        console.log('Worker ' + worker.process.pid + ' is online');
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
        console.log('Starting a new worker');
        cluster.fork();
    });
} else {
    var app = require('express')();
    app.all('/*', function(req, res) {res.send('process ' + process.pid + ' says hello!').end();})

    var server = app.listen(8000, function() {
        console.log('Process ' + process.pid + ' is listening to all incoming requests');
    });
}
登入後複製

這裡需要注意的一點是,message事件回調是異步處理的。沒有定義的執行順序。您可以在GitHub上找到主進程和工作進程之間通信的完整示例。

零停機時間

使用工作進程可以實現的一個重要結果是(幾乎)零停機時間服務器。在主進程中,您可以在對應用程序進行更改後,一次一個地終止和重新啟動工作進程。這允許您在加載新版本的同時運行舊版本。為了能夠在運行時重新啟動應用程序,您需要記住兩點。首先,主進程一直運行,只有工作進程被終止和重新啟動。因此,重要的是要使主進程保持簡短,並且只負責管理工作進程。其次,您需要以某種方式通知主進程需要重新啟動工作進程。有幾種方法可以做到這一點,包括用戶輸入或監視文件更改。後者效率更高,但您需要在主進程中識別要監視的文件。我建議重新啟動工作進程的方法是首先嘗試安全地關閉它們;然後,如果它們沒有安全終止,則強制殺死它們。您可以通過向工作進程發送關閉消息來執行前者,如下所示:

worker.on('message', function(message) {
    console.log(message);
});
登入後複製

並在工作進程message事件處理程序中啟動安全關閉:

process.on('message', function(message) {
    console.log(message);
});
登入後複製

要對所有工作進程執行此操作,您可以使用集群模塊的workers屬性,該屬性保存對所有正在運行的工作進程的引用。我們還可以將所有任務包裝在主進程中的一個函數中,該函數可以在我們想要重新啟動所有工作進程時調用。

var cluster = require('cluster');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

我們可以從集群模塊中的workers對象獲取所有正在運行的工作進程的ID。此對象保存對所有正在運行的工作進程的引用,並在終止和重新啟動工作進程時動態更新。首先,我們將所有正在運行的工作進程的ID存儲在workerIds數組中。這樣,我們避免重新啟動新派生的工作進程。然後,我們請求每個工作進程安全關閉。如果5秒後工作進程仍在運行並且仍然存在於workers對像中,那麼我們調用工作進程上的kill函數以強制其關閉。您可以在GitHub上找到一個實際示例。

結論

可以使用集群模塊對Node.js應用程序進行並行化,以便更有效地使用系統。可以使用幾行代碼同時運行多個進程,這使得遷移相對容易,因為Node.js處理困難的部分。正如我在性能比較中所展示的那樣,通過更有效地利用系統資源,應用程序性能有可能得到顯著提高。除了性能之外,您還可以通過在應用程序運行時重新啟動工作進程來提高應用程序的可靠性和正常運行時間。也就是說,在考慮在應用程序中使用集群模塊時,您需要注意。集群模塊的主要推薦用途是用於Web服務器。在其他情況下,您需要仔細研究如何在工作進程之間分配任務,以及如何在工作進程和主進程之間有效地溝通進度。即使對於Web服務器,在對應用程序進行任何更改之前,也要確保單個Node.js進程是瓶頸(內存或CPU),因為您的更改可能會引入錯誤。最後一點,Node.js網站為集群模塊提供了很好的文檔。因此,請務必查看一下!

關於Node.js集群的常見問題解答(FAQ)

使用Node.js集群的主要優勢是什麼?

使用Node.js集群的主要優勢是提高應用程序的性能。 Node.js在一個線程上運行,這意味著它一次只能利用一個CPU內核。但是,現代服務器通常有多個內核。通過使用Node.js集群,您可以創建一個主進程,該進程派生多個工作進程,每個工作進程都在不同的CPU內核上運行。這允許您的應用程序同時處理更多請求,從而顯著提高其速度和性能。

Node.js集群是如何工作的?

Node.js集群通過創建一個主進程來工作,該主進程派生多個工作進程。主進程偵聽傳入請求並將它們以輪詢方式分發給工作進程。每個工作進程都在單獨的CPU內核上運行並獨立處理請求。這允許您的應用程序利用所有可用的CPU內核並同時處理更多請求。

如何創建一個Node.js集群?

創建Node.js集群涉及使用Node.js提供的“cluster”模塊。首先,您需要導入“cluster”和“os”模塊。然後,您可以使用“cluster.fork()”方法來創建工作進程。 “os.cpus().length”為您提供可用的CPU內核數,您可以使用它來確定要創建的工作進程數。這是一個簡單的示例:

var cluster = require('cluster');
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

如何處理Node.js集群中的工作進程崩潰?

您可以通過偵聽主進程上的“exit”事件來處理Node.js集群中的工作進程崩潰。當工作進程崩潰時,它會向主進程發送“exit”事件。然後,您可以使用“cluster.fork()”方法來創建一個新的工作進程以替換崩潰的工作進程。這是一個示例:

if(cluster.isMaster) { ... }
登入後複製
登入後複製
登入後複製

我可以將Node.js集群與Express.js一起使用嗎?

是的,您可以將Node.js集群與Express.js一起使用。事實上,使用Node.js集群可以顯著提高Express.js應用程序的性能。您只需要將Express.js應用程序代碼放在集群腳本中的工作進程代碼塊中即可。

Node.js集群的局限性是什麼?

雖然Node.js集群可以顯著提高應用程序的性能,但它也有一些局限性。例如,工作進程不共享狀態或內存。這意味著您不能將會話數據存儲在內存中,因為它在所有工作進程中都不可訪問。相反,您需要使用共享會話存儲,例如數據庫或Redis服務器。

如何在Node.js集群中負載均衡請求?

默認情況下,Node.js集群中的主進程以輪詢方式將傳入請求分發給工作進程。這提供了一種基本的負載均衡形式。但是,如果您需要更高級的負載均衡,則可能需要使用反向代理服務器,例如Nginx。

我可以在生產環境中使用Node.js集群嗎?

是的,您可以在生產環境中使用Node.js集群。事實上,強烈建議在生產環境中使用Node.js集群,以充分利用服務器的CPU內核並提高應用程序的性能。

如何調試Node.js集群?

調試Node.js集群可能有點棘手,因為您有多個工作進程同時運行。但是,您可以對每個工作進程使用具有唯一端口的“inspect”標誌來將調試器附加到每個進程。這是一個示例:

cluster.fork();
登入後複製
登入後複製
登入後複製

我可以將Node.js集群與其他Node.js模塊一起使用嗎?

是的,您可以將Node.js集群與其他Node.js模塊一起使用。但是,您需要注意的是,工作進程不共享狀態或內存。這意味著如果模塊依賴於共享狀態,它可能無法在集群環境中正常工作。

以上是如何創建一個node.js群集以加速您的應用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

JavaScript難以學習嗎? JavaScript難以學習嗎? Apr 03, 2025 am 12:20 AM

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

如何實現視差滾動和元素動畫效果,像資生堂官網那樣?
或者:
怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? 如何實現視差滾動和元素動畫效果,像資生堂官網那樣? 或者: 怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? Apr 04, 2025 pm 05:36 PM

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

console.log輸出結果差異:兩次調用為何不同? console.log輸出結果差異:兩次調用為何不同? Apr 04, 2025 pm 05:12 PM

深入探討console.log輸出差異的根源本文將分析一段代碼中console.log函數輸出結果的差異,並解釋其背後的原因。 �...

See all articles