什麼是cluster子產品,為什麼需要cluster子產品?
cluster在英文中有集、群的意思。
nodejs預設是單程序的,但是對于多核的cpu來說, 單程序顯然沒有充分利用cpu,是以,node中的cluster子產品就是為了解決沒有充分利用cpu的問題而産生的。
cluster子產品如何使用?
cluster子產品允許設立一個主程序和若幹個worker程序(一般,我們對于産生的不是主程序的程序或者線程都用worker這個詞來表示,打工者的意思),由主程序監控和協調worker程序的運作。worker之間采用程序間通信交換消息,cluster子產品内置一個負載均衡器,采用Round-robin算法協調各個worker程序之間的負載。運作時,所有建立立的連結都由主程序完成,然後主程序再把TCP連接配接配置設定給指定的worker程序。
var cluster = require('cluster');
var os = require('os');
if (cluster.isMaster){
for (var i = 0, n = os.cpus().length; i < n; i += 1){
cluster.fork();
}
} else {
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}
可以看到使用 cluster 子產品是非常簡單的,首先引入 cluster 子產品,然後判斷cup的個數,根據個數來建立子程序。 如果目前不是主程序,那麼就啟動一個伺服器。
但是,如果哪個程序挂了,我們無法檢測到,是以,使用一個 online 和 exit來監聽 :
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();
});
}
上面代碼中,主程序一旦監聽到worker程序的exit事件,就會重新開機一個worker程序。worker程序一旦啟動成功,可以正常運作了,就會發出online事件。
worker對象的使用
worker對象是
cluster.fork()
的傳回值,注意:fork方法可以傳回一個v8執行個體,代表一個worker程序。屬性和方法如下:
(1)worker.id
worker.id傳回目前worker的獨一無二的程序編号。這個編号也是cluster.workers中指向目前程序的索引值
(2)worker.process
所有的worker程序都是用child_process.fork()生成的。child_process.fork()傳回的對象,就被儲存在worker.process之中。通過這個屬性,可以擷取worker所在的程序對象。
(3)worker.send()
該方法用于在主程序中,向子程序發送資訊
if (cluster.isMaster) {
var worker = cluster.fork();
worker.send('hi there');
} else if (cluster.isWorker) {
process.on('message', function(msg) {
process.send(msg);
});
}
上面代碼的作用是,worker程序對主程序發出的每個消息,都做回聲。
在worker程序中,要向主程序發送消息,使用
process.send(message)
;要監聽主程序發出的消息,使用下面的代碼。
process.on('message', function(message) {
console.log(message);
});
});
發出的消息可以字元串,也可以是JSON對象。
cluster.workers對象
該對象隻有主程序才有,包含了所有worker程序。每個成員的鍵值就是一個worker程序對象,鍵名就是該worker程序的worker.id屬性。
function eachWorker(callback) {
for (var id in cluster.workers) {
callback(cluster.workers[id]);
}
}
eachWorker(function(worker) {
worker.send('big announcement to all workers');
});
cluster子產品的屬性和方法
isMaster,isWorker
isMaster屬性傳回一個布爾值,表示目前程序是否為主程序。這個屬性由process.env.NODE_UNIQUE_ID決定,如果process.env.NODE_UNIQUE_ID為未定義,就表示該程序是主程序。
isWorker屬性傳回一個布爾值,表示目前程序是否為work程序。它與isMaster屬性的值正好相反。
fork()
fork方法用于建立一個worker程序,上下文都複制主程序。隻有主程序才能調用這個方法。
該方法傳回一個worker對象。
kill()
kill方法用于終止worker程序。它可以接受一個參數,表示系統信号。
如果目前是主程序,就會終止與worker.process的聯絡,然後将系統信号法發向worker程序。如果目前是worker程序,就會終止與主程序的通信,然後退出,傳回0。
在以前的版本中,該方法也叫做 worker.destroy() 。