Nodejs極簡(jiǎn)入門教程(三):進(jìn)程
Node 雖然自身存在多個(gè)線程,但是運(yùn)行在 v8 上的 JavaScript 是單線程的。Node 的 child_process 模塊用于創(chuàng)建子進(jìn)程,我們可以通過子進(jìn)程充分利用 CPU。范例:
var fork = require('child_process').fork;
// 獲取當(dāng)前機(jī)器的 CPU 數(shù)量
var cpus = require('os').cpus();
for (var i = 0; i < cpus.length; i++) {
// 生成新進(jìn)程
fork('./worker.js');
}
這里了解一下包括 fork 在內(nèi)的幾個(gè)進(jìn)程創(chuàng)建方法:
1.spawn(command, [args], [options]),啟動(dòng)一個(gè)新進(jìn)程來執(zhí)行命令 command,args 為命令行參數(shù)
2.exec(command, [options], callback),啟動(dòng)一個(gè)新進(jìn)程來執(zhí)行命令 command,callback 用于在進(jìn)程結(jié)束時(shí)獲取標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出,以及錯(cuò)誤信息
3.execFile(file, [args], [options], [callback]),啟動(dòng)一個(gè)新進(jìn)程來執(zhí)行可執(zhí)行文件 file,callback 用于在進(jìn)程結(jié)束時(shí)獲取標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出,以及錯(cuò)誤信息
4.fork(modulePath, [args], [options]),啟動(dòng)一個(gè)新進(jìn)程來執(zhí)行一個(gè) JavaScript 文件模塊,這時(shí)候創(chuàng)建的是 Node 子進(jìn)程
Node 進(jìn)程間通信
父進(jìn)程
// parent.js
var fork = require('child_process').fork;
// fork 返回子進(jìn)程對(duì)象 n
var n = fork('./child.js');
// 處理事件 message
n.on('message', function(m) {
// 收到子進(jìn)程發(fā)送的消息
console.log('got message: ' + m);
});
// 向子進(jìn)程發(fā)送消息
n.send({hello: 'world'});
子進(jìn)程
// child.js
// 處理事件 message
process.on('message', function(m) {
console.log('got message: ' + m);
});
// process 存在 send 方法,用于向父進(jìn)程發(fā)送消息
process.send({foo: 'bar'});
需要注意的是,這里的 send 方法是同步的,因此不建議用于發(fā)送大量的數(shù)據(jù)(可以使用 pipe 來代替,詳細(xì)見:http://nodejs.org/api/all.html#child_process_child_process_spawn_command_args_options)。
特殊的情況,消息中 cmd 屬性值包含 NODE_ 前綴(例如:{cmd: ‘NODE_foo'} 消息),那么此消息不會(huì)被提交到 message 事件(而是 internalMessage 事件),它們被 Node 內(nèi)部使用。
send 方法的原型為:
send(message, [sendHandle])
這里,sendHandle(handle)可以被用于發(fā)送:
1.net.Native,原生的 C++ TCP socket 或者管道
2.net.Server,TCP 服務(wù)器
3.net.Socket,TCP socket
4.dgram.Native,原生的 C++ UDP socket
5.dgram.Socket,UDP socket
send 發(fā)送 sendHandle 時(shí)實(shí)際上不是(也不能)直接發(fā)送 JavaScript 對(duì)象,而是發(fā)送文件描述符(最終以 JSON 字符串發(fā)送),其他進(jìn)程能夠通過這個(gè)文件描述符還原出對(duì)應(yīng)對(duì)象。
現(xiàn)在看一個(gè)例子:
父進(jìn)程
// parent.js
var fork = require('child_process').fork;
var n = fork('./child.js');
var server = require('net').createServer();
server.listen(7000, function() {
// 發(fā)送 TCP server 到子進(jìn)程
n.send('server', server);
}).on('connection', function() {
console.log('connection - parent');
});
子進(jìn)程
process.on('message', function(m, h) {
if (m === 'server') {
h.on('connection', function() {
console.log('connection - child');
});
}
});
通過端口 7000 訪問此程序,得到輸出可能為 connection – parent 也可能得到輸出 connection – child。這里子進(jìn)程和父進(jìn)程同時(shí)監(jiān)聽了端口 7000。通常來說,多個(gè)進(jìn)程監(jiān)聽同一個(gè)端口會(huì)引起 EADDRINUSE 的異常,而此例的情況是,不同的兩個(gè)進(jìn)程使用了相同的文件描述符,且 Node 底層在監(jiān)聽端口時(shí)對(duì) socket 設(shè)置了 SO_REUSEADDR 選項(xiàng),這使得此 socket 可以在不同的進(jìn)程間復(fù)用。在多個(gè)進(jìn)程監(jiān)聽同一個(gè)端口時(shí),同一時(shí)刻文件描述符只能被一個(gè)進(jìn)程使用,這些進(jìn)程對(duì) socket 的使用是搶占式的。
cluster 模塊
在 Node 的 v0.8 新增了 cluster 模塊,通過 cluster 模塊能夠輕松的在一臺(tái)物理機(jī)器上構(gòu)建一組監(jiān)聽相同端口的進(jìn)程。范例:
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
// 檢查進(jìn)程是否是 master 進(jìn)程
if (cluster.isMaster) {
for (var i = 0; i < numCPUs; ++i)
// 生成新的 worker 進(jìn)程(只有 master 進(jìn)程才可以調(diào)用)
cluster.fork();
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
http.createServer(function(req, res) {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
}
我們?cè)?worker 進(jìn)程中調(diào)用 listen 方法,監(jiān)聽請(qǐng)求將會(huì)傳遞給 master 進(jìn)程。如果 master 進(jìn)程已經(jīng)存在一個(gè)正在監(jiān)聽的 server 符合 worker 進(jìn)程的要求,那么此 server 的 handle 將會(huì)傳遞給 worker,如果不存在,master 進(jìn)程則會(huì)創(chuàng)建一個(gè),然后將 handle 傳遞給 worker 進(jìn)程。
更多詳細(xì)的關(guān)于 cluster 的文檔:http://www.nodejs.org/api/cluster.html
相關(guān)文章
基于Node-red的在線評(píng)語(yǔ)系統(tǒng)(可視化編程,公網(wǎng)訪問)
Node-Red是IBM公司開發(fā)的一個(gè)可視化的編程工具,在網(wǎng)頁(yè)內(nèi)編程,主要是拖拽控件,代碼量很小,這篇文章主要介紹了基于Node-red的在線評(píng)語(yǔ)系統(tǒng)(可視化編程,公網(wǎng)訪問),需要的朋友可以參考下2022-01-01安裝Node.js并啟動(dòng)本地服務(wù)的操作教程
今天小編就為大家分享一篇安裝Node.js并啟動(dòng)本地服務(wù)的操作教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05Express進(jìn)階之log4js實(shí)用入門指南
本篇文章主要介紹了Express進(jìn)階之log4js實(shí)用入門指南,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02Node.js實(shí)現(xiàn)大文件斷點(diǎn)續(xù)傳示例詳解
這篇文章主要為大家介紹了Node.js實(shí)現(xiàn)大文件斷點(diǎn)續(xù)傳示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Nodejs進(jìn)階:express+session實(shí)現(xiàn)簡(jiǎn)易登錄身份認(rèn)證
本篇文章主要介紹了Nodejs進(jìn)階:express+session實(shí)現(xiàn)簡(jiǎn)易身份認(rèn)證示例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-04-04nodejs版本過高導(dǎo)致vue2版本的項(xiàng)目無法正常啟動(dòng)的解決方案
這篇文章主要給大家介紹了關(guān)于nodejs版本過高導(dǎo)致vue2版本的項(xiàng)目無法正常啟動(dòng)的解決方案,本文小編給大家詳細(xì)介紹了如何解決這個(gè)問題,如有遇到同樣問題的朋友可以參考下2023-11-11