Like Share Discussion Bookmark Smile

J.J. Huang   2020-02-11   Node.js   瀏覽次數:

Node.js | multi-process(多進程)

簡介

Node.js是以單線程的模式運行的,但它使用的是事件驅動來處理並發,這樣有助於我們在多核cpu的系統上建立多個子進程,從而提高性能。

每個子進程總是帶有三個流對象:child.stdinchild.stdoutchild.stderr。他們可能會共享父進程的stdio流,或者也可以是獨立的被導流的流對象。

Node提供了child_process模組來建立子進程,方法:

  • execchild_process.exec使用子進程執行指令,緩存子進程的輸出,並將子進程的輸出以回調函數參數的形式返回。
  • spawnchild_process.spawn使用指定的指令行參數建立新進程。
  • forkchild_process.forkspawn()的特殊形式,用於在子進程中運行的模組,如fork('./son.js')相當於spawn('node', ['./son.js' ])。與spawn方法不同的是,fork會在父進程與子進程之間,建立一個通信管道,用於進程之間的通信。

exec()

child_process.exec使用子進程執行指令,緩存子進程的輸出,並將子進程的輸出以回調函數參數的形式返回。

語法

1
child_process.exec(command[, options], callback)

參數

參數使用說明如下:

  • command:字符串, 將要運行的指令,參數使用空格隔開。
  • options:對象,可以是:
型態 說明
cwd <string> 子進程的當前工作目錄。默認值:null。
env <Object> 環境鍵值對。 默認值:process.env。
encoding <string> 默認值:utf8。
shell <string> 用Shell執行指令。 請參閱外殼程序要求和默認Windows Shell。 默認值:在Unix上為“ / bin / sh”,在Windows上為process.env.ComSpec。
timeout <number> 默認值:0。
maxBuffer <number> stdout或stderr上允許的最大資料量(以字節為單位)。如果超過,子進程將終止,所有輸出都將被截斷。 請參見maxBuffer和Unicode的警告。默認值:1024 * 1024。
killSignal <string> , <integer> 默認值:“ SIGTERM”
uid <number> 設置進程的用戶身份。
gid <number> 設置進程的組標識。
windowsHide <boolean> 隱藏通常在Windows系統上建立的子進程控制台窗口。默認值:false。
  • callback:回調函數,包含三個參數error, stdout 和 stderr。
型態
error <Error>
stdout <string> , <Buffer>
stderr <string> , <Buffer>

exec()方法返回最大的緩衝區,並等待進程結束,一次性返回緩衝區的內容。

實例

建立兩個js文件support.jsmaster.js

1
2
// support.js
console.log("進程 " + process.argv[2] + " 執行。" );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// master.js
const fs = require('fs');
const child_process = require('child_process');
 
for(var i=0; i<3; i++) {
    var workerProcess = child_process.exec('node support.js '+i, function (error, stdout, stderr) {
        if (error) {
            console.log(error.stack);
            console.log('Error code: '+error.code);
            console.log('Signal received: '+error.signal);
        }
        console.log('stdout: ' + stdout);
        console.log('stderr: ' + stderr);
    });
 
    workerProcess.on('exit', function (code) {
        console.log('子進程已退出,退出碼 '+code);
    });
}

執行結果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ node master.js
子進程已退出,退出碼 0
子進程已退出,退出碼 0
子進程已退出,退出碼 0
stdout: 進程 2 執行。

stderr:
stdout: 進程 1 執行。

stderr:
stdout: 進程 0 執行。

stderr:

spawn()

child_process.spawn使用指定的指令行參數建立新進程。

語法

1
child_process.spawn(command[, args][, options])

參數

參數使用說明如下:

  • command:將要運行的指令。

  • argsArray字符串參數數組。

  • options:對象,可以是:

型態 說明
cwd <string> 子進程的當前工作目錄。
env <Object> 環境鍵值對。默認值:process.env。
argv0 <string> 顯式設置發送給子進程的argv [0]的值。如果未指定,則將其設置為command。
stdio <Array> , <string> 子級的stdio配置。
detached <boolean> 準備讓子代獨立於其父進程運行。具體行為取決於平台。
uid <number> 設置進程的用戶身份。
gid <number> 設置進程的組標識。
serialization <string> 指定用於在進程之間發送消息的序列化類型。可能的值為“ json”和“ advanced”。有關更多詳細訊息,請參見高級序列化。默認值:“ json”。
shell <boolean> , <string> 如果為true,則在shell內運行指令。在Unix上使用“ / bin / sh”,在Windows上使用process.env.ComSpec。可以將其他外殼指定為字符串。請參閱外殼程序要求和默認Windows Shell。默認值:false(無外殼)。
windowsVerbatimArguments <boolean> 在Windows上不執行引號或轉義參數。在Unix上被忽略。當指定外殼且為CMD時,此選項將自動設置為true。默認值:false。
windowsHide <boolean> 隱藏通常在Windows系統上建立的子進程控制台窗口。默認值:false。

spawn()方法返回流(stdout&stderr),在進程返回大量資料時使用。進程一旦開始執行時spawn()就開始接收響應。

實例

建立兩個js文件support.jsmaster.js

1
2
// support.js
console.log("進程 " + process.argv[2] + " 執行。" );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// master.js
const fs = require('fs');
const child_process = require('child_process');
 
for(var i=0; i<3; i++) {
   var workerProcess = child_process.spawn('node', ['support.js', i]);
 
   workerProcess.stdout.on('data', function (data) {
      console.log('stdout: ' + data);
   });
 
   workerProcess.stderr.on('data', function (data) {
      console.log('stderr: ' + data);
   });
 
   workerProcess.on('close', function (code) {
      console.log('子進程已退出,退出碼 '+code);
   });
}

執行結果如下:

1
2
3
4
5
6
7
8
9
10
$ node master.js
stdout: 進程 0 執行。

stdout: 進程 1 執行。

stdout: 進程 2 執行。

子進程已退出,退出碼 0
子進程已退出,退出碼 0
子進程已退出,退出碼 0

fork()

child_process.forkspawn()方法的特殊形式,用於建立進程。

語法

1
child_process.fork(modulePath[, args][, options])

參數

參數使用說明如下:

  • modulePathString,將要在子進程中運行的模組。

  • argsArray字符串參數數組。

  • options:對象,可以是:

型態 說明
cwd <string> 子進程的當前工作目錄。
detached <boolean> 準備讓子代獨立於其父進程運行。具體行為取決於平台。
env <Object> 環境鍵值對。默認值:process.env。
execPath <string> 可執行文件,用於建立子進程。
execArgv <string[]> 傳遞給可執行文件的字符串參數列表。默認值:process.execArgv。
serialization <string> 指定用於在進程之間發送消息的序列化類型。可能的值為“ json”和“ advanced”。有關更多詳細訊息,請參見高級序列化。默認值:“ json”。
silent <boolean> 如果為true,則將子級的stdin,stdout和stderr通過管道傳遞給父級,否則它們將從父級繼承,請參見child_process.spawn()的stdio的’pipe’和’inherit’選項以獲取更多詳細訊息。默認值:false。
stdio <Array> , <string> 請參閱child_process.spawn()的stdio。提供此選項後,它將覆蓋無聲。如果使用數組變體,則它必須恰好包含一個值為“ ipc”的項目,否則將引發錯誤。例如[0,1,2,’ipc’]。
windowsVerbatimArguments <boolean> 在Windows上不執行引號或轉義參數。在Unix上被忽略。默認值:false。
uid <number> 設置進程的用戶身份。
gid <number> 設置進程的組標識。

返回的對象除了擁有ChildProcess實例的所有方法,還有一個內建的通信信道。

實例

建立兩個js文件support.jsmaster.js

1
2
// support.js
console.log("進程 " + process.argv[2] + " 執行。" );
1
2
3
4
5
6
7
8
9
10
11
// master.js
const fs = require('fs');
const child_process = require('child_process');
 
for(var i=0; i<3; i++) {
   var worker_process = child_process.fork("support.js", [i]);
 
   worker_process.on('close', function (code) {
      console.log('子進程已退出,退出碼 ' + code);
   });
}

執行結果如下:

1
2
3
4
5
6
7
$ node master.js
進程 0 執行。
進程 1 執行。
進程 2 執行。
子進程已退出,退出碼 0
子進程已退出,退出碼 0
子進程已退出,退出碼 0


註:以上參考了
Node.js 多进程
Node.js child_process Documentation