本篇文章帶大家了解一下node中的Nodejs-cluster模組,介紹一下Nodejs-cluster模組的用法,希望對大家有幫助!
面試官有時候會問你,你給我說下nodejs如何開啟多進程哇,你腦海裡就應該立刻出現cluster模組,如今讓我帶你去探討下cluster模組的使用。
Node.js預設單一進程運行,對於32位元系統最高可以使用512MB內存,對於64位元最高可以使用1GB記憶體。對於多核心CPU的電腦來說,這樣做效率很低,因為只有一個核心在運行,其他核心都在閒置。 cluster模組就是為了解決這個問題而提出的。
cluster模組允許設立一個主進程和若干個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.isMaster),如果是的,就依照CPU的核數,新建若干個worker進程;如果不是,表示當前進程是worker進程,則在該進程啟動一個伺服器程式。
上面這段程式碼有一個缺點,就是一旦work進程掛了,主程式無法知道。為了解決這個問題,可以在主行程部署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()的回傳值,代表一個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物件。下面是一個發送JSON物件的例子。
worker.send({ type: 'task 1', from: 'master', data: { // the data that you want to transfer } });
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'); });
上面程式碼用來遍歷所有worker進程。
目前socket的data事件,也可以用id屬性辨識worker行程。
socket.on('data', function(id) { var worker = cluster.workers[id]; });
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() 。
listening事件
worker程序呼叫listening方法以後,「listening」事件就傳到該行程的伺服器,然後傳向主程序。
該事件的回呼函數接受兩個參數,一個是目前worker對象,另一個是位址對象,包含網址、連接埠、位址類型(IPv4、IPv6、Unix socket、UDP)等資訊。這對於那些服務多個網址的Node應用程式非常有用。
不中斷地重啟Node服務
重启服务需要关闭后再启动,利用cluster模块,可以做到先启动一个worker进程,再把原有的所有work进程关闭。这样就能实现不中断地重启Node服务。
首先,主进程向worker进程发出重启信号。
workers[wid].send({type: 'shutdown', from: 'master'});
worker进程监听message事件,一旦发现内容是shutdown,就退出。
process.on('message', function(message) { if(message.type === 'shutdown') { process.exit(0); } });
下面是一个关闭所有worker进程的函数。
function restartWorkers() { var wid, workerIds = []; for(wid in cluster.workers) { workerIds.push(wid); } workerIds.forEach(function(wid) { cluster.workers[wid].send({ text: 'shutdown', from: 'master' }); setTimeout(function() { if(cluster.workers[wid]) { cluster.workers[wid].kill('SIGKILL'); } }, 5000); }); };
PM2模块
PM2模块是cluster模块的一个包装层。它的作用是尽量将cluster模块抽象掉,让用户像使用单进程一样,部署多进程Node应用。
// app.js var http = require('http'); http.createServer(function(req, res) { res.writeHead(200); res.end("hello world"); }).listen(8080);
用PM2从命令行启动这段代码
$ pm2 start app.js -i 4
上面代码的i参数告诉PM2,这段代码应该在cluster_mode启动,且新建worker进程的数量是4个。如果i参数的值是0,那么当前机器有几个CPU内核,PM2就会启动几个worker进程。
如果一个worker进程由于某种原因挂掉了,会立刻重启该worker进程。
# 重启所有worker进程 $ pm2 reload all
每个worker进程都有一个id,可以用下面的命令查看单个worker进程的详情。
$ pm2 show <worker id>
关闭worker进程的时候,可以部署下面的代码,让worker进程监听shutdown消息。一旦收到这个消息,进行完毕收尾清理工作再关闭
process.on('message', function(msg) { if (msg === 'shutdown') { close_all_connections(); delete_logs(); server.close(); process.exit(0); } });
更多node相关知识,请访问:nodejs 教程!!
以上是聊聊Nodejs-cluster模組,介紹一下其使用方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!