
## åè¨
è¿ç¨ä¸çº¿ç¨ä½ä¸ºæä½ç³»ç»çåºç¡æ¦å¿µï¼æ¯ä¸ä¸ªè½¯ä»¶å¼åå·¥ç¨å¸å¿ é¡»éè¦ææ¡çãèå¨å¼å Node.js ç¨åºæ¶ï¼è¿ç¨ä¸çº¿ç¨ä¹ä¼åæ¥æ¯è¾å¤§çä½ç¨ã
æ¬æä¸»è¦ä¸»è¦è®² Node.js ä¸å¤è¿ç¨çéæ±åºæ¯ä¸è§£å³æ¹æ¡ã
æ¬æçææ demo è§ï¼https://github.com/ImHype/process-and-thread-in-nodejs
## è¿ç¨æ¯ä»ä¹?
è¿ç¨æ¯è¿ç°ä»£æä½ç³»ç»ç产ç©ãè®¡ç®æºç¡¬ä»¶å±é¢å ¶å®æ²¡æè¿ç¨ä¸çº¿ç¨çæ¦å¿µï¼å®åçäºæ å°±æ¯ä¸åå°è¿è¡æºå¨ç ã
æ©æçæä½ç³»ç»è®¾è®¡åºæ¥æ¯å任塿§è¡æºå¨ç çï¼ä»»å¡çæ§è¡ååå å«é 置任å¡ï¼åæåç»æä¸¤ä¸ªå¨ä½ï¼æä»¬æä»ä»¬ç§°ä¸ºâ䏿ºâä¸â䏿ºâã
èéçè®¡ç®æºè®¡ç®è½åçæåï¼äººä»¬åç°â䏿ºâåâ䏿ºâçå¨ä½ä¼æä¸ºæ´ä¸ªç³»ç»çç¶é¢ï¼äººçéåº¦å¤ªæ ¢äºï¼ãæä»¥ä¾¿è®¾è®¡äºå¤éç¨åºæ¹å¤çæä½ç³»ç»ã
æ¤æ¶çæä½ç³»ç»è½å¤ç»è®¡ç®æºå®æä¸ä¸ªéåäºï¼è®©è®¡ç®æºä¸æä»éåä¸è¯»åä»»å¡ï¼æ§è¡ï¼æç»å°ç»æè®°å½å°åå¨ä»è´¨éé¢ï¼æç¹åç°å¨ç CI Runnerã
ä½é®é¢ä¼¼ä¹æ²¡ææ ¹æ¬è§£å³ï¼äººä»¬åç°å½ä¸äºä»»å¡æ§è¡éè¦çå¾ ä¸äºå¤é¨æä½ï¼æ¯å¦ç½ç»è¯·æ±ãæä»¶è¯»åï¼æ¤æ¶è®¡ç®èµæºè¿æ¯ä¼å¤äºæµªè´¹ç¶æã
é®é¢å¾å°å®è´¨æ§çè§£å³ï¼æ¯æ¶åå¤ç¨æä½ç³»ç»çå¼å ¥ï¼æ¯ä¸ªä»»å¡æä»¥ä¸ç¶æä¸å忢ã
éè¿è¿ç§æ¹å¼ï¼å¤ä¸ªä»»å¡è½å¤è¢«ãå¹¶åãå°æ§è¡ãå建任å¡åï¼éè¿æ¶åå¤ç¨çæºå¶ï¼ç± CPU è°åº¦æ§è¡ï¼å½ä»»å¡éè¦çå¾ å¤é¨èµæºæ¶ï¼åè¿å ¥é»å¡æï¼æ¤æ¶æ æ³åç± CPU è°åº¦æ§è¡ï¼ç´å°å¤é¨èµæºå·²å°±ç»ªåï¼ç±ç³»ç»ä¸æè§¦åï¼å°å ¶ä»»å¡ç¶æå次置为就绪æï¼èå该任å¡åå¯ç± CPU è°åº¦æ§è¡ã
çæ£è®©å¤è¿ç¨ä½ç¨åæ¥å°æè´ï¼æ¯å¯¹ç§°å¤å¤çææ¯ (SMPï¼å 许å¤ä¸ªå¤çå¨å ±äº«å ååè®¡ç®æºèµæº) çæçï¼è½å¤è®©å¤ä»»å¡çæ§è¡å¨å¤ä¸ªå¤çå¨ä¸å¹¶è¡è¿è¡ã
ä¸è¿°æå°çä»»å¡ï¼å°±æ¯è¿ç¨ï¼åç§°è°åº¦ä¸»ä½ãåæ ·ä½ä¸ºè°åº¦ä¸»ä½èåå¨çè¿æã线ç¨ãï¼å¨ Linux 2.4 åæ´æ©ï¼çº¿ç¨çå®ç°å ¶å®ä¹æ¯è¿ç¨ï¼èå¨å¾åççæ¬éï¼ä»»å¡è°åº¦ç主ä½åæäºçº¿ç¨ï¼è¿ç¨æä¸ºäºçº¿ç¨å®¹å¨ã
è¿ç¨ä½ä¸ºçº¿ç¨ç容å¨ï¼å ·å¤å½¼æ¤ç¬ç«çå å空é´ãè¿åæä¹çè§£å¢ï¼
æä»¬å¨ç¨åºä¸ä½¿ç¨çï¼é½æ¯é»è¾å°åï¼æ¯å¦ 0x0ï¼ï¼è¿ä¸ªå°åæ å°å°çå®çç©çå°åéè¦ä¸ä¸ªéå®åè¿ç¨ï¼ç±ç¡¬ä»¶å±é¢ç MMU 宿ã
å¨ç°ä»£æä½ç³»ç»å帧å页çå åç®¡çæ¨¡å¼ä¸ï¼è¿ç¨çé»è¾å°åè¢«åæ®µãå帧表示ãåæ®µæ¯æï¼ä»£ç æ®µãæ°æ®æ®µãbss 段ãå æ®µãæ æ®µï¼åé¡µæ¯æå°è¿ç¨å ç使ç¨ç©ºé´å°é»è¾å°ååæä¸ä¸ªä¸ªè¿ç»ç大å°ç¸ççåå ãå°å®é çç©çå åä¸ä¹åæä¸ä¸ªä¸ªå页大å°ç¸ççåå ï¼ç§°ä¹ä¸ºå¸§ï¼ä½å¸§å æ°æ®åå¨å¯ä»¥ä¸è¿ç»ãå®é çå å读åè¿ç¨æ¯ï¼MMU ä¼ä»é»è¾å°å计ç®å¾å°é¡µå·å页å åç§»éï¼ç»å pid æ¥åå页表å¾å°å¸§å·ï¼åæ¼æ¥å¸§å·å页å åç§»éå¾å°çå®çç©çå°åãåé¡µææ¯è§£å³çæ¯å åå¤é¨ç¢çé®é¢ã
é常æ åµä¸ï¼ä¸åçè¿ç¨åªæç¨å°åä¸ä¸ªå¨æé¾æ¥åºæ¶ï¼ä»£ç 段ä¼å ±äº«å å帧ï¼å ¶ä½çæ®µé½æ¯ä¸å ±äº«çãæç»å¯¼è´çæ¯ï¼ä¸åçè¿ç¨æ¥æåèªç¬ç«çå å空é´åèµæºï¼å¦æä»¶æè¿°ç¬¦ï¼ç«¯å£ççï¼èåä¸ä¸ªè¿ç¨ä¸çä¸å线ç¨ï¼å¯ä»¥å ±äº«è¿ç¨å®¹å¨çå å空é´ä¸èµæºã
## å¤è¿ç¨çéæ±
å¨å¸¸è§ç web æå¡å¨é¢åï¼é»è®¤æ¨¡å¼ä¸è¿è¡ Node ç¨åºé叏伿è¿ä¸¤ä¸ªçç¹ï¼
- æä»¬ Node.js ç¨åºï¼ä¼è¿è¡å¨éåæ ¸ CPU ç宿主ç¯å¢ï¼è䏿æå° JavaScript çæ§è¡æ¯å¨å线ç¨ä¸æ§è¡çãä¹å°±æ¯è¯´å¦ææä»¬çåºç¨æ¯ ã计ç®å¯éåã åºç¨ï¼åè¿ç¨çè¿è¡æ¨¡å¼ä¸æä»¬æ¯æ æ³å åå©ç¨ CPU çèµæºçï¼
- åè¿ç¨ç Node.js ç¨åºå´©æºéåºäºæä¹åï¼
## å¤è¿ç¨çè§£å³æ¹æ¡
ç®å主æµçæä¸¤ä¸ªè§£å³æ¹æ¡ï¼
- éç Docker çæ®åï¼æ¬èº«æä¾äº Daemon çæºå¶ï¼å¯ä»¥å¸®å©é坿们çåºç¨ï¼å¹¶ä¸ Docker 乿¯æåé 1 core ç计ç®èµæºï¼
- 使ç¨è¿ç¨ç®¡çå·¥å · - PM2ï¼ä»¥ âclusterâ æ¨¡å¼å¯å¨ã
å¦ä½å¯¹ä¸¤ç§æ¹æ¡è¿è¡åèå¢ï¼
æè®¤ä¸ºå¦æä½ çå ¬å¸æä¾äº Docker çé¨ç½²æ¹æ¡ï¼å¯ä»¥å°è¯æ¨¡æä¸è¿ç¨å¼å¸¸éåºçæ åµï¼è§å¯ä¸è¿ç¨éæ°æèµ·çæ¶é´ï¼å pm2 æ¹æ¡åä¸ä¸ªç®å对æ¯ï¼å¦ææèµ·çéåº¦åºæ¬æ å·®ï¼å¯ä»¥ä½¿ç¨æ¹æ¡ 1ï¼å¦åå¯ä»¥ç»§ç»ä½¿ç¨ pm2 çæ¹æ¡ã
é£ä¹é常æä»¬å¨ Docker ä¸è¿è¡ pm2ï¼æ¯è¦ä»¥ no-daemon 模å¼è¿è¡çï¼å¦å Docker 容å¨ä¼ä¸æéå¯ï¼ï¼
$ pm2 start server.js --no-daemon -i 2
好ï¼ç®å为æ¢ï¼æä»¬äºè§£äº Node.js å¨å¸¸è§ web æå¡å¼åçéæ±åºæ¯ï¼æ¥ä¸æ¥æä»¬å°è¯ä¸èµ·æ¥å®ç°ä¸ä¸ªã麻éè½å°ï¼äºèä¿±å ¨ãçè¿ç¨ç®¡çå·¥å ·ï¼ä»¥å¸®å©å¤§å®¶çæ Node.js ä¸åççè¿ç¨æä½ã
## å®ç°ä¸æ¬¾ç±»ä¼¼ pm2 çè¿ç¨ç®¡çå·¥å ·
ç¹å«è¯´æï¼æä»¬åè¿ä¸ªè¿ç¨ç®¡çå·¥å ·çç®çï¼ä¸æ¯ä¸ºäºè®©å®è½å¤å¨çå®ç线ä¸ç¯å¢ä¸è·ï¼èæ¯ä¸ºäºéè¿è¿ä¸ªä¾åï¼å¸®å©å 深对 Node.js çè¿ç¨æºå¶ççè§£ã
å æ´çä¸ä¸ä¸ªåºæ¬çè¿ç¨ç®¡çå·¥å ·æéè¦æ¥æçåè½ï¼
- åºç¡çåè¿ç¨å建è½åï¼
- åè¡¡å°å°è¯·æ±ååå°å个åè¿ç¨ï¼
- åè¿ç¨å¼å¸¸éåºæ¶ï¼è¦è½éå¯åè¿ç¨ï¼
- 宿¤è¿ç¨è¦è½å¨åå°å¸¸é©»è¿è¡ï¼
- æ¥æ¶éåºå½ä»¤ï¼éåºææåè¿ç¨ï¼å¹¶éæ¾èµæºï¼
- æ¶éå·¥ä½è¿ç¨çæ¥å¿ã
æä»¬ä¸ä¸ªä¸ªæ¥çã
### å建åè¿ç¨çè½å
Node.js æä¾çåºç¡å¤è¿ç¨å¤çè½åå ç§å¨ child_process 模åã
æä¾äºåç§å建åè¿ç¨çæ¹å¼ï¼
- exec
- execFile
- fork
- spawn
å ¶ä¸ï¼exec ä¸ execFile 主è¦ç¨æ¥æ§è¡ç³»ç»å½ä»¤ï¼è spawn æ¯å ¶ä½ä¸ä¸ªå½æ°çåºç¡ï¼å ¶ä»ä¸ä¸ªå½æ°å é¨é½ä¼è°ç¨ spawn 彿°ã
å¯¹äºæ¬æ¬¡éæ±ï¼æä»¬ä¸»è¦è®²è§£ fork 彿°ã
å个 ä¾å æ¥æåä¸ fork 彿°çåºç¡ç¨æ³ï¼
é¦å æ¯ main.js
// main.js
const { fork } = require('child_process');
const sub = fork('./child.js', {
stdio: 'inherit'
});
sub.on('message', (msg) => {
console.log(msg);
});
ç¶åæ¯ child.js
// child.js
process.send('hello');
console.log('hello world');
æåçè¾åºæ¯ï¼
> hello world
> hello
䏿¬¡ç®åçåè¿ç¨åå»ºä¾¿å®æäºã
### å¤è¿ç¨å¯å¨ web server
使ç¨ä¸ä¸èå¦ä¹ å°ç fork API æ¥è¯çå建æä»¬çæå¡ï¼çä¾åã
// fork.js
const { fork } = require('child_process');
for (let i = 0; i < 4; i++) {
fork('./main.js');
}
// main.js
const http = require('http');
http.createServer((req, res) => {
res.end('hello');
}).listen(3000);
ä¼¼ä¹åæä»¬ pm2 ç使ç¨å§¿å¿ç±»ä¼¼ï¼ææè½å¤å®ç°æä»¬çéæ±ãä½åç°æç»çç»ææ¯è¿æ ·çï¼
æç¤ºä½ 端å£è¢«å ç¨äºï¼ä¸ºä»ä¹ä¼è¿æ ·å¢ï¼
- å颿们æå°è¿ç¨æ¯æ¥æç¬ç«çèµæºï¼å æ¬å å空é´ä»¥å端å£åæä»¶æè¿°ç¬¦çï¼
- æä»¥ï¼å½ä¸ä¸ªç«¯å£è¢«ä¸ä¸ªè¿ç¨å ç¨ä¹åï¼å ¶ä»è¿ç¨å°±æ æ³åå ç¨äºã
é£é®é¢æä¹è§£å³å¢ï¼ä¸è¬æä¸é¢å ç§æ¹æ¡ï¼
第ä¸ç§æ¹æ¡æ¯ï¼ç±»å Nginx çæ¨¡å¼ï¼èµ·ä¸ä¸ª master è¿ç¨ç¨äºæ¥æ¶ http 请æ±ï¼åéè¿ http 代ççå½¢å¼ä»£çå°åè¿ç¨ãä½å¨åä¸å°æºå¨å çç¶åè¿ç¨ä¹é´éè¿è¿æ ·çå½¢å¼è¿è¡äº¤äºæ¯å¯è½æ§è½ä¼åºç°ç¶é¢ã
第äºç§æ¹æ¡ä¾¿æ¯åºç¨ child_process æä¾ç»æä»¬çè¿ç¨é´éä¿¡æºå¶ï¼
- process.on(âmessageâ, callback);
- process.send(âmessageâ, handle);
æ¥çä¾åã
// master.js
const { fork } = require('child_process');
const net = require('net');
const subprocess = fork('child.js', []);
const server = net.createServer((socket) => {
subprocess.send('accept', socket);
});
server.listen(9999);
// child.js
process.on('message', (msg, handle) => {
if (msg === 'accept') {
const body = Buffer.from('<html><head><title>Wrox Homepage</title></head><body>hello world</body></html>');
handle.end(`HTTP/1.1 200 OKrnDate: Sat, 31 Dec 2005 23:59:59 GMTrnContent-Type: text/html;charset=utf-8rnContent-Length: ${Buffer.byteLength(body)}rnrn${body}`);
}
})
node master.js
æ§è¡ï¼å¯ä»¥åç°æåå¯å¨äºï¼å¹¶ä¸è®¿é®
localhost:9999
乿åååºäº
hello world
ã è¿ä¸ªæ¹æ¡è½è¿è¡çåçæ¯ï¼
- æä»¶æè¿°ç¬¦æºå¶ï¼ä»¥ä¸ç§° fdï¼ï¼
- ç³»ç»çº§æä¾ IPC æºå¶å 许è¿ç¨è§ä¼ é fdï¼
- Node.js å±é¢å©ç¨ä»¥ä¸ç³»ç»çº§ç¹æ§åäºå°è£ ï¼æ¯æ process.send æ¹å¼ä¼ é socketã
ä½è¿ä¸ªæ¹æ¡ä¹æ´é²äºä¸ä¸ªé®é¢ï¼ 对å¯å¨ç server ä»£ç æä¾µå ¥æ§ã
第ä¸ä¸ªæ¹æ¡æ¯ä½¿ç¨ Node.js æ¬èº«æä¾ç cluster æºå¶ï¼ç±äº cluster 模åå é¨ä»¥ hack çå½¢å¼å¸®æä»¬åäºç±»ä¼¼æ¹æ¡äºçäºæ ï¼ä½¿å¾å¤è¿ç¨å¯å¨çé»è¾ä¸åä¾µå ¥ server ç代ç ï¼çä¾åã
// master.js
const cluster = require('cluster');
cluster.setupMaster({
exec: 'worker.js',
});
const workers = [];
for (let i = 0; i < 4; i++) {
const child = cluster.fork()
workers.push(child);
}
// worker.js
const http = require('http');
http.createServer((req, res) => {
res.end('hello');
}).listen(9000, () => {
console.log('process %s started', process.pid)
});
æ¹æ¡ä¸ cluster çæºå¶çèµ·æ¥æ¯ä¸ç§è¾ä¼çæºå¶ï¼ç¨äºè§£å³å¤è¿ç¨å¯å¨çé®é¢ã
### è¿ç¨å®æ¤
妿æä»¬ç server å 为æä¸ªå¼å¸¸å¯¼è´äºè¿ç¨éåºï¼è¿ä¸ªæ¶å该æä¹åï¼
ä½ä¸ºä¸æ¬¾è¿ç¨ç®¡çå·¥å ·ï¼éè¦åçå°±æ¯éå¯åè¿ç¨ï¼æä»¬ç§°å®ä¸ºè¿ç¨å®æ¤ã大è´å为两个æ¥éª¤ï¼
- çå¬åè¿ç¨éåºï¼
- è¿ç¨éåºåéæ° `refork` åè¿ç¨ã
çå¬åè¿ç¨éåºï¼éè¦å©ç¨ç Node.js æä¾çæºå¶æ¯åè¿ç¨äºä»¶æºå¶ï¼å°¤å ¶è¦ç¨å° exit äºä»¶ãæ¥çä¾åãæä»¬ç master.js å¯ä»¥æ¹æè¿ä¸ªæ ·åã
// master.js
const cluster = require('cluster');
cluster.setupMaster({
exec: 'worker.js',
});
const workers = [];
const fork = () => {
const child = cluster.fork();
console.log('pid %s', child.pid);
child.on('exit', () => {
workers.splice(workers.indexOf(child), 1);
setTimeout(() => {
fork();
}, 1000);
});
workers.push(child);
}
for (let i = 0; i < 4; i++) {
fork();
}
è¿ä¸ªæ¶åæä»¬è¯çç¨ kill å½ä»¤ææå¯¹åºçåè¿ç¨ï¼åç°åè¿ç¨é坿åã
ä¹å°±æ¯æä»¬çè¿ç¨å®æ¤å·²çæã
### åå°å¸¸é©»çéæ±
æä»¬ç¥é pm2 æä¸ªè¿ç¨å¸¸é©»åå°è¿è¡çåè½ã
æä»¬å¸ææä»¬çç¨åºå¨ç»ç«¯éåºä¹åè¿è½è¿è¡ï¼æä¹å®ç°å¢ï¼
çæ bash çåå¦ç¥é bash éé¢å¯ä»¥è¿æ ·
$ nohup server.js &
对åºå° c è¯è¨éé¢æä¸ª setsidï¼ä¹æ¯å¹²è¿ä¸ªäºæ ãé£ node.js é颿ä¹å®ç°è¿ä¸ªéæ±ï¼
å¯ä»¥å¨è°ç¨ fork æ¶ä¼ å ¥ options.detachedï¼æä»¬æ¥ç个ä¾åã
å¨ä¹åå建ç master.js å worker.js çå级ç®å½ä¸ï¼å建 command.jsï¼å 容å¦ä¸ã
const { fork } = require('child_process');
const child = fork('./master.js', {
detached: true,
stdio: 'ignore'
});
process.exit(0);
æ§è¡
node command.js
ä¹åï¼åç°å½åè¿ç¨é©¬ä¸éåºäºï¼è ps æ¥çåç° worker å master ä»å¨åå°å¸¸é©»ï¼ä¸ master è¿ç¨ç ppid åæäº 1ã
æ¾ç¶æ¯ç¬¦åæä»¬ææçã
### 忢åå°è¿è¡çè¿ç¨
å¨åå°è¿è¡çè¿ç¨ï¼å¦ææä»¬æ³è¦ç»æè¿è¡ï¼ä¼¼ä¹æä»¬å¯ä»¥æä¸é®çç ctrl + cã
èè¿ç¨å¨åå°è¿è¡ä¹åï¼å¦ææä»¬æ³è¦ç»æå®çæ¶åï¼è¯¥æä¹åå¢ï¼
è¿éè¦ä»ç» ä¿¡å·æºå¶ã
å®é 䏿们æä¸é®çç ctrl + c çæä½ï¼å ¶å®ä¹æ¯è§¦åäºå¯¹å½ååå°è¿ç¨çä¸ä¸ªä¿¡å·ï¼è¿ä¸ªä¿¡å·å°±æ¯ SIGINTãåæ ·çï¼è¿ææä»¬å¸¸ç¨ç kill å½ä»¤ï¼æ¯ shell ç»ç¨æ·æä¾ç触åç®æ è¿ç¨ä¿¡å·çæ¹å¼ãæ¯å¦è¯´ä»¥ä¸æä½ä¼å¼ºå¶ç»æè¿ç¨è¿è¡ã
$ kill -9 pid
å½ç¶æä»¬æ´æ¨èä½¿ç¨ SIGTERM ä¿¡å·ï¼å 为è¿ç¨å¨æ¥æ¶å°è¿ä¸ªä¿¡å·æ¶ï¼ä¸è¬å 许åä¸äºåæ¶å·¥ä½ï¼æ¯å¦âä¼é âæå¼ä¸è¿ç¨æå¡çé¿è¿æ¥ã
$ kill pid
é£ Node.js é颿ä¹ä½¿ç¨å¢ï¼æä»¬ç´æ¥ç» command.js å ä¸äºä»£ç ï¼ä»¥å®ç°æä»¬éè¦çâ忢åå°è¿è¡è¿ç¨âåè½ã
const { fork } = require('child_process');
const fs = require('fs');
const pidfile = '.pid';
if (process.argv[2] === 'stop') {
const pid = fs.readFileSync(pidfile, 'utf8');
process.kill(Number(pid), 'SIGTERM');
fs.unlinkSync(pidfile);
} else {
const child = fork('./master.js', {
detached: true,
stdio: 'ignore'
});
fs.writeFileSync(pidfile, String(child.pid));
process.exit(0);
}
ç¶åè¯ç卿¬å°æ§è¡ï¼åç°è½å¤æåç»æå¨åå°è¿è¡çè¿ç¨ã
注æï¼ä¹åè¿è¡çè¿ç¨è¦å æå¨ææã
### ä¼é éåº
é¦å è¦ä»ç»ä¸ä¸ªå¤å¿è¿ç¨çæ¦å¿µãå½åè¿ç¨å¨éåºæ¶ï¼å¦æåè¿ç¨è¿å¨è¿è¡ï¼åè¿ç¨ä¼ç§°ä¸ºå¤å¿è¿ç¨ï¼è¡¨ç°æ¯ ppid ä¼åæ 1ï¼å¥½åååå°å¸¸é©»è¿ç¨çç»æå¾åãä¾åå¨è¿éã
æä»¥è¿ç¨å®æ¤å·¥å ·å¨ç»æè¿ç¨æ¶ï¼è¦èèå°è¿ä¸ç¹ï¼ä¹å°±æ¯å¨æ¥æ¶å°è¿ç¨éåºçå½ä»¤ï¼ç»ææææçåè¿ç¨ï¼è¿æ¯éè¿ä¸ä¸èæå°çä¿¡å·æºå¶ã
è¿éè¿ç¨ç®¡çå·¥å ·éè¦åä¸¤ä»¶äºæ ï¼
- æ¥æ¶éåºä¿¡å·ï¼å¯¹åºå° Node.js å æ¯ä¿¡å·çäºä»¶æºå¶ï¼
- å©ç¨ ps å½ä»¤æ¾åºå½åè¿ç¨çææåè¿ç¨ï¼å¯ä»¥åå© npm å ps-tree å®ç°ã
const cluster = require('cluster');
const util = require('util');
const pstree = require('ps-tree');
cluster.setupMaster({
exec: 'worker.js',
});
const workers = [];
const fork = () => {
const child = cluster.fork();
child.on('exit', () => {
workers.splice(workers.indexOf(workers), 1);
setTimeout(() => {
fork();
}, 1000);
});
workers.push(child);
}
for (let i = 0; i < 4; i++) {
fork();
}
process.on('SIGTERM', signalExit);
process.on('SIGQUIT', signalExit);
process.on('SIGINT', signalExit);
function signalExit() {
Promise.all(workers.map((w) => new Promise((resolve) => {
pstree(w.process.pid, (e, children) => {
if (e) {
console.log(e);
resolve([]);
} else {
resolve(children);
}
})
})))
.then((results) => {
results.forEach((pids) => {
pids.forEach((pid) => {
process.kill(pid.PID, 'SIGTERM');
})
});
process.exit(0);
}).catch(() => {
process.exit(1);
});
}
åæ ·å°ï¼æä»¬ç SIGTERM éé¢è¿å¯ä»¥ç»§ç»åä¸äºå ¶ä»çåæ¶å·¥ä½ï¼æ¯å¦æå¼ä¸æå¡ç«¯çé¿è¿æ¥ï¼æ¸ 餿¬å°çç¼åæä»¶ççã
### æ¥å¿è®°å½
å°ç®å为æ¢ï¼æä»¬é½æ²¡æå¤çæ åè¾åºæµï¼å 为æä»¬çè¿ç¨ç´æ¥éåºäºï¼ä¸äº console æå°çæ¥å¿ä¼¼ä¹å°±æ¶å¤±æ 踪äºï¼è¿æ¯ä¸è¢«å¸æçãæä»¬å¸æçæ¯è½å¤å°åè¿ç¨çæ åè¾åºéå®åå°æ¬å°çä¸äºæ¥å¿æä»¶ã
å¯ä»¥åå© fork æ¶ä¼ å ¥ç options.stdio æ¥å®ç°è¿ä¸ªéæ±ã
console.log, console.error çæä½å ¶å®æ¯å¾ 1 å 2 çæä»¶æè¿°ç¬¦éé¢åå ¥å 容ãè options.stdio è½å¤éæ°å®åçæä»¶æè¿°ç¬¦ã以ä¸çæä½å°±è½å¤å° 1 å 2 çæè¿°ç¬¦æåæ¬å°æä»¶ã
const { fork } = require('child_process');
const fs = require('fs');
const pidfile = '.pid';
if (process.argv[2] === 'stop') {
const pid = fs.readFileSync(pidfile, 'utf8');
process.kill(Number(pid), 'SIGTERM');
fs.unlinkSync(pidfile);
} else {
const applog = fs.openSync('./app.log', 'a+');
const errorlog = fs.openSync('./app-error.log', 'a+');
const child = fork('./master.js', {
detached: true,
stdio: [0, applog, errorlog, 'ipc']
});
fs.writeFileSync(pidfile, String(child.pid));
process.exit(0);
}
è¿æ¬¡å¯å¨ä¹åï¼åç°å¨åè¿ç¨éé¢çæ åè¾åºæåè¿å ¥å°äº app.log å app-error.log æä»¶å ã宿鿱ã
## å°ç»
éè¿æ¬æçå¦ä¹ ï¼æä»¬éè¿ä¸ä¸ªè¿ç¨ç®¡çå·¥å ·çè½®åï¼çæäº
- å建åè¿ç¨çæ¹å¼ï¼
- exec/execFile/spawn/fork
- IPC æºå¶å®ç°è¿ç¨é´å
±ç¨ Socket çéæ±ï¼
- IPC éä¿¡ä¼ é socket ï¼åçæ¯ç³»ç»çº§ç IPC éä¿¡ä¼ éæä»¶æè¿°ç¬¦ï¼
- æç»ä½¿ç¨ cluster çè§£å³æ¹æ¡ï¼
- ä½¿ç¨ è¿ç¨äºä»¶ çå¬åè¿ç¨éåºï¼ç¶åè¿è¡ reforkï¼
- ä½¿ç¨ options.detached æ¥å建åå°å¸¸é©»è¿ç¨ï¼
- éè¿ ä¿¡å·æºå¶ å®ç°åå°å¸¸é©»è¿ç¨çéåºï¼
- äºè§£å¤å¿è¿ç¨çåå¨ï¼å¹¶éè¿ çå¬ä¿¡å· çæ¹å¼ï¼æ¥å®ç°ä¼é éåºï¼
- çè§£æä»¶æè¿°ç¬¦ï¼éè¿ options.stdio æå®åè¿ç¨çæä»¶æè¿°ç¬¦ï¼å®ç°æ åè¾å ¥è¾åºéå®åå°æ¥å¿çéæ±ã
æ ç²çé¨åå¯ä»¥ç»å Node.js 宿¹ææ¡£æ·±å ¥çè§£ã忬¡æ¾ä¸æ¬æä¾åç龿¥ï¼https://github.com/ImHype/process-and-thread-in-nodejsã
ææä¸æ¡å¹¿åã
åèè·³å¨è¯éä¼ç§çå端工ç¨å¸åNode.js
å·¥ç¨å¸å å
¥ï¼ä¸èµ·åæè¶£çäºæ
ï¼æ¬¢è¿ææè
ç§ä¿¡èç³»ï¼æåéç®åè³ [email protected]ã æ ¡ææ³ è¿é
ãï¼åæ ·æ¬¢è¿å®ä¹ çåå¦ã
好äºï¼æä»¬ä¸æåä¼ã