简要介绍:我们知道nodejs本身是一个单进程单线程,并且使用驱动模式来处理并发,对于多核CPU,如果仅仅使用单进程,其实是很浪费资源的,因此nodejs提供了cluster模块和child_process模块来创建多个子进程,从而提高cpu的利用率。
1.首先我们来看用cluster来创建多个子进程的方式
var cluster = require('cluster');
var os = require('os');
// 获取CPU 的数量
var numCPUs = os.cpus().length;
var workers = {};
if (cluster.isMaster) {
// 主进程分支
cluster.on('death', function (worker) {
// 当一个工作进程结束时,重启工作进程
delete workers[worker.pid];
worker = cluster.fork();
workers[worker.pid] = worker;
});
// 初始开启与CPU 数量相同的工作进程
for (var i = 0; i < numCPUs; i++) {
var worker = cluster.fork();
workers[worker.pid] = worker;
}
} else {
// 工作进程分支,启动服务器
var app = require('./app');
app.listen(3000);
}
// 当主进程被终止时,关闭所有工作进程
process.on('SIGTERM', function () {
for (var pid in workers) {
process.kill(pid);
}
process.exit(0);
});
这段代码的核心是创建与cpu核心个数相同的服务器进程,以确保充分利用多核CPU的资源。主进程生成若干个工作进程,并监听工作进程结束事件,当工作进程结束时,重新启动一个工作进程,分支进程会自顶向下重新当前程序(也就是在子进程中,如果新开了子进程,也会执行这段代码),并通过分支判断进入工作进程分支,在其中读取模块并启动服务器。
注意:通过cluster启动工作进程,可以直接实现端口复用,因此所有工作进程只需要监听同一个端口,当主进程终止还需要关闭所有的工作进程。
2.通过child_process来实现多进程
方法有下面三种:
(1)exec
(2)spawn
(3)fork
并且每一个子进程总是带有3个流对象,child_stdin,child_stdout,child_stderr.它们会共享父进程的stdio流。举一个exec创建子进程的例子:
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);
});
}
上述代码的输出结果:
$ node master.js
子进程已退出,退出码 0
stdout: 进程 1 执行。
stderr:
子进程已退出,退出码 0
stdout: 进程 0 执行。
stderr:
子进程已退出,退出码 0
stdout: 进程 2 执行。
stderr:
3.cluster和child_process之间的区别
最大区别在于cluster允许跨进程端口复用,给我们的网络服务器带来很大的方便,也就是可以在同一个服务器端口,利用cluster实现多进程。