天天看點

nodejs(四) --- cluster子產品詳解

什麼是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() 。

listening事件

繼續閱讀