跳到主要內容

Nodejs cluste

 由於Javascript本身設計就適合於單線程的應用, 但一般後端應用程式都會支援多個服務來處理client的請求, nodejs中也提供了cluster模組來達成此功能。


Cluster的原理很簡單,由於每個Process都只能用單核心的CPU來運行,那麼就多開幾個來幫忙處理吧! 而這個Cluster的模組強大的地方在於讓我們只監聽一個Port,加上Master/Worker的概念,當收到請求後就分配給底下的Worker進行處理。

這樣有什麼好處? 遇到尖峰時刻時,我們可以妥善利用多核的優勢,避免有些CPU閒置造成浪費。



如何實做?

根據系統的cpu數量建立N個worker來進行處理。

// server.js
const cluster = require('cluster');
const cpuNums = require('os').cpus().length;
const http = require('http');
if (cluster.isMaster) {
    console.info(`cpu: ${cpuNums}`);
    for (var i = 0; i < cpuNums; i++) {
        cluster.fork();
    }
} else {
    http.createServer(function(req, res) {
        res.end(`response from worker ${process.pid}`);
    }).listen(5000);
    console.log(`Worker ${process.pid} started`);
}

建立測試腳本

for ((i = 1; i <= 8; i++)); do
    curl <http://127.0.0.1:5000>
    echo ""
done

輸出如下, 可以看到response來自不同的worker:

response from worker 7872
response from worker 7878
response from worker 7886
response from worker 7893
response from worker 7853
response from worker 7860
response from worker 7855
response from worker 7866

master、worker如何通訊?

master透過cluster.fork()來建立worker。

cluster.fork()內部是藉由child_process.fork()來建立。

如何將請求分發到多個worker

每個worker建立時都會於master上註冊並建立IPC通道, 而客戶端請求到達時, master會負責將請求分配給worker。

這裡可能會有疑問是這些請求是如何被分配的?採取什麼策略?

預設的分配策略是輪詢的方式, 當請求到達時, master會輪詢一遍worker列表, 看誰有空閒就將請求分配給該worker進行處理。



另外也支援無分配策略但這種方式可能會造成搶食現象的競爭問題。

可以透過環境變數NODE_CLUSTER_SCHED_POLICY設定, 也可以在cluster.setupMaster(options)時傳入。

process之間的通訊



由於各個process無法共享資源, 但可以藉由IPC通訊方式讓master與worker之間進行通信, 基本用法如下:

// worker 發送訊息
process.send('讀取訊息');

// master 接收消息 -> 處理 -> 回應
cluster.on('online', function (worker) {
     // worker建立時,開始監聽message事件
     cluster.workers[id].on('message', function(data) {
          // 處理來自worker發送的資料
          // 回傳給worker
          cluster.workers[id].send('result')
     });
});

🔔還沒成為Potato會員的朋友點這裡加入哦,撰寫文章還能挖礦打造被動收入 🔔

留言

這個網誌中的熱門文章

java西元民國轉換_各種不同格式

C#資料庫操作(新增、修改、刪除、查詢)