参考:
https://github.com/ElemeFE/node-interview/blob/master/sections/zh-cn/process.md#child-process

node的单线程,以单一进程运行,因此无法利用多核CPU以及其他资源,为了调度多核CPU等资源,node还提供了child_process模块 和 cluster模块(v0.8之后)来支持多进程

1 child_process

提供给node随意创建子进程的能力,提供4个方法

方法 进程类型 执行类型
spawn 任意 命令
excu 任意 命令
excuFile 任意 可执行文件
focus Node js文件
  1. // master.js
  2. var cp = require('child_process');
  3. cp.spawn("node", ["work.js"])
  4. cp.exec("node worker.js", function (err, stdout, stderr) {
  5. //code
  6. })
  7. cp.execFile("worker.js", function (err, stdout, stderr) {
  8. //code
  9. })
  10. cp.fork("./worker.js")
  11. //worker.js
  12. // #! /usr/bin/env node 如果作为可执行文件被excuFile调用,必须保留本首行
  13. var http = require('http');
  14. http.createServer(function (req, res) {
  15. res.writeHead(200, {'Content-Type': 'text/plain'});
  16. res.end('Hello World\n');
  17. }).listen(Math.round((1 + Math.random()) * 1000), '127.0.0.1');

! /usr/bin/env node 如果作为可执行文件被excuFile调用,首行必须是这样
参考
shell脚本

1.1 进程间通信IPC(inner-process communication)

通过folk创建的node进程,会在父子进程间创建IPC通道,可以通过message和send传递消息
比如:
master.js
image.png
child.js
image.png
执行结果
image.png

1.2 句柄传递—实现多进程共同监听同一端口

参考:深入浅出nodejs —9.2.3
Node在版本v0.5.9引入了进程间发送句柄的功能。send()方法除了能通过IPC发送数据外,还能发送句柄,第二个可选参数就是句柄
image.png

  1. //parent.js
  2. var child = require('child_process').fork('child.js');
  3. // Open up the server object and send the handle
  4. var server = require('net').createServer();
  5. server.on('connection', function (socket) {
  6. socket.end('handled by parent\n');
  7. });
  8. server.listen(1337, function () {
  9. child.send('server', server);
  10. });
  1. // child.js
  2. process.on('message', function (m, server) {
  3. if (m === 'server') {
  4. server.on('connection', function (socket) {
  5. socket.end('handled by child\n');
  6. });
  7. }
  8. });

测试结果:
node parent.js
image.png
子进程和父进程都有可能处理我们客户端发起的请求。

1.3 进程事件

1.3.1 父进程监听子进程事件

image.png
image.png
image.png

1.3.1 进程监听信号事件

Node提供了这些信号对应的信号事件,每个进程都可以监听这些信号事件。这些信号事件是用来通知进程的,每个信号事件有不同的含义,进程在收到响应信号时,应当做出约定的行为
信号参考:
进程
image.png
image.png
有了父子进程之间的相关事件之后,就可以做一些自动重启等来保证服务的稳定性

2 cluster

参考 egg多进程/ node-cluster官方文档
image.png

官方示例

  1. const cluster = require('cluster');
  2. const http = require('http');
  3. const numCPUs = require('os').cpus().length;
  4. if (cluster.isMaster) {
  5. console.log(`Master ${process.pid} is running`);
  6. // Fork workers.
  7. for (let i = 0; i < numCPUs; i++) {
  8. cluster.fork();
  9. }
  10. cluster.on('exit', (worker, code, signal) => {
  11. console.log(`worker ${worker.process.pid} died`);
  12. });
  13. } else {
  14. // Workers can share any TCP connection
  15. // In this case it is an HTTP server
  16. http.createServer((req, res) => {
  17. res.writeHead(200);
  18. res.end(`hello world + pid-->${process.pid}\n`);
  19. }).listen(8000);
  20. console.log(`Worker ${process.pid} started`);
  21. }

启动 inspect模式
image.png
查看node进程
image.png