背景
node的父子進程中可以傳遞這是肯定的,但是傳遞對象,這是一個稀奇的地方。
code
發送 server 對象
sendHandle 參數可用於將一個 TCP server 對象句柄傳給子進程,如下所示:
const subprocess = require('child_process').fork('subprocess.js');
// 開啟 server 對象,並發送該句柄。
const server = require('net').createServer();
server.on('connection', (socket) => {
socket.end('被父進程處理');
});
server.listen(1337, () => {
subprocess.send('server', server);
});
子進程接收 server 對象如下:
process.on('message', (m, server) => {
if (m === 'server') {
server.on('connection', (socket) => {
socket.end('被子進程處理');
});
}
});
當服務器在父進程和子進程之間是共享的,則一些連接可被父進程處理,另一些可被子進程處理。
上面的例子使用了一個 net 模塊創建的服務器,而 dgram 模塊的服務器使用完全相同的工作流程,但它監聽一個 'message' 事件而不是 'connection' 事件,且使用 server.bind 而不是 server.listen()。 目前僅 UNIX 平台支持這一點。
傳遞socket
例子:發送 socket 對象
同樣,sendHandle 參數可用於將一個 socket 句柄傳給子進程。 以下例子衍生了兩個子進程,分別用於處理 "normal" 連接或優先處理 "special" 連接:
const { fork } = require('child_process');
const normal = fork('subprocess.js', ['normal']);
const special = fork('subprocess.js', ['special']);
// 開啟 server,並發送 socket 給子進程。
// 使用 `pauseOnConnect` 防止 socket 在被發送到子進程之前被讀取。
const server = require('net').createServer({ pauseOnConnect: true });
server.on('connection', (socket) => {
// 特殊優先級。
if (socket.remoteAddress === '74.125.127.100') {
special.send('socket', socket);
return;
}
// 普通優先級。
normal.send('socket', socket);
});
server.listen(1337);
subprocess.js 會接收到一個 socket 句柄,並作為第二個參數傳給事件回調函數:
process.on('message', (m, socket) => {
if (m === 'socket') {
if (socket) {
// 檢查客戶端 socket 是否存在。
// socket 在被發送與被子進程接收這段時間內可被關閉。
socket.end(`請求被 ${process.argv[2]} 優先級處理`);
}
}
});
一旦一個 socket 已被傳給了子進程,則父進程不再能夠跟蹤 socket 何時被銷毀。 為了表明這個,.connections 屬性會變成 null。 當發生這種情況時,建議不要使用 .maxConnections。
建議在子進程中的任何 message 處理程序都需要驗證 socket 是否存在,因為連接可能會在它在發送給子進程的這段時間內被關閉。