Node.js Cluster 模組:利用多核心 CPU 實現水平擴展
預設情況下,Node.js 程式運行在單一個 CPU 核心上。如果你的伺服器擁有 8 核心甚至更多,那麼其餘的核心將會處於閒置狀態。Cluster (叢集) 模組允許你輕鬆啟動多個子進程,將連線酬載均勻分配到所有核心,達成真正的水平擴展。
運作原理:Primary 與 Workers
在 Node.js 16+ 之後,官方推薦使用 Primary 替代舊稱的 Master。
- Primary (主進程):負責管理、監控與分配任務,本身不處理具體的網路請求。
- Workers (工作進程):真正的執行者。多個 Worker 共享同一個 TCP 連線埠 (Port),由 Primary 以 Round-Robin (輪詢) 演算法自動分配傳入的請求。
基礎實戰範例
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isPrimary) {
console.log(`主進程 ${process.pid} 正在啟動,預計分配給 ${numCPUs} 個核心...`);
// 根據核心數產生對應的工作者
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
// 監聽結束事件:當某個 Worker 崩潰時自動重啟
cluster.on('exit', (worker, code, signal) => {
console.warn(`工作進程 ${worker.process.pid} 已離線,正在自動遞補...`);
cluster.fork();
});
} else {
// 每個工作進程都會獨立跑一個 HTTP Server
http
.createServer((req, res) => {
res.writeHead(200);
res.end(`由進程 ID: ${process.pid} 為您服務`);
})
.listen(8080);
console.log(`工作進程 ${process.pid} 已就緒`);
}
為什麼要使用 Cluster?
- 效能翻倍:隨著核心數增加,伺服器的總吞吐量會呈線性成長。
- 高可用性 (High Availability):如果其中一個工作進程因為程式 Bug 崩潰,主進程可以立即拉起一個新的補充,整個系統幾乎可以做到 零停機 (Zero Downtime)。
核心限制:記憶體隔離
由於每個 Worker 都是獨立的作業系統進程,因此它們 不能共享全域變數。
- ❌ 錯誤做法:在 JavaScript 全域變數裡計算「連線總數」,每個 Worker 都只會讀到自己的局部數字。
- ✅ 正確做法:將需要共享的狀態存放在外部的 Redis 或資料庫中。
專業部署建議:PM2
雖然 cluster 模組很好用,但在實際的生產環境中,Node.js 開發者通常會選擇使用 PM2。
PM2 是一個內建了 Cluster 模式的進程管理器,它提供了更強大的日誌管理、自動監控排程以及優雅重啟 (Graceful Reload) 功能。
總結
cluster是解決 Node.js 單核限制的內建方案。- 它適合處理大量的網路連線 (I/O 密集型)。
- 在生產環境中,推薦了解
cluster原理後改用 PM2 進行自動化管理。