眾所周知,Node.js是單線程的,一個單獨的Node.js進程無法充分利用多核。Node.js從v0.6.0開始,新增cluster模塊,讓Node.js開發Web服務時,很方便的做到充分利用多核機器。
充分利用多核的思路是:使用多個進程處理業務。cluster模塊封裝了創建子進程、進程間通信、服務負載均衡。有兩類進程,master進程和worker進程,master進程是主控進程,它負責啟動worker進程,worker是子進程、干活的進程。
簡單的demo代碼如下:
/* * cluster module's example * 2016.02.16 * cswuyg * */ 'use strict'; var cluster = require('cluster'); var http = require('http'); var cpuCount = require('os').cpus().length; if (cluster.isMaster) { for (var i = 0; i < cpuCount; ++i) { cluster.fork(); } } else { http.createServer(function(req, res) { res.writeHead(200); res.end('hello world\n'); console.log(cluster.worker.id); }).listen(8000); }
注意和其它:
1、負載均衡問題
一個web請求過來,是給worker進程A處理,還是worker進程B處理呢?怎么保證大家均等的干活呢? 這就是負載均衡的問題。
當前有兩種可選的方法來做負載均衡。
早期的cluster是各個worker進程自己去監聽socket端口,由操作系統去喚醒worker進程,大家可能很容易認為操作系統會隨機的選擇worker進程,於是就實現了服務的負載均衡。但實際上,像Linux操作系統總是喚醒某幾個進程,因為對於系統來說,上下文切換時很昂貴的操作,喚醒最近被喚醒的進程是比較好的選擇。早期的這種方式負載是很不均衡的。
從0.11.2版本開始,cluster開始增加了round-robin模式做負載均衡:master進程負責監聽,收到請求后轉發給worker進程,多個worker進程輪流干活。
round-robin是當前cluster的默認負載均衡處理模式(除了windows平台),如果要回到之前的模式,有兩種方式,
(1)可以在cluster加載之后未調用其它cluster函數之前執行:cluster.schedulingPolicy = cluster.SCHED_NONE; 來設定。
(2)設置環境變量NODE_CLUSTER_SCHED_POLICY="none",例如:NODE_CLUSTER_SCHED_POLICY="none" node b.js > a.log。 可選值為:'rr'和'none'。
2、進程監控問題
master進程不會自動管理worker進程的生死,如果worker被外界殺掉了,不會自動重啟,只會給master進程發送‘exit’消息,開發者需要自己做好管理。
3、數據共享問題
各個worker進程之間是獨立的,為了讓多個worker進程共享數據(譬如用戶session),一般的做法是在Node.js之外再搭建一個數據庫,多個worker進程通過數據庫做數據共享。
4、一些測試和練習代碼
官方資料:https://nodejs.org/api/cluster.html
學習資料:http://www.infoq.com/cn/articles/nodejs-cluster-round-robin-load-balancing
nodejs changelog:https://github.com/nodejs/node/blob/v4.3.0/CHANGELOG.md
