为啥需要多进程
nodejs中javascript是运行在单线程上的,无法充分榨干多核系统资源,并行的处理更多的用户请求。
nodejs中的多进程使用
依赖cluster
模块
const cluster = require('cluster');
const http = require('http');
const os = require('os');
const cpus = os.cpus().length;
// console.log(cluster);
if(cluster.isMaster) {
console.log('Master process run at pid: %d', process.pid);
for(let i = 0; i<cpus; i++) {
// 内部基于child_process.fork()实现
// child_process.fork()默认的
cluster.fork();
cluster.on('exit', (worker, code, signal)=> {
console.log(`worker ${worker.process.pid} died`);
})
}
} else {
http.createServer(function (req,res) {
res.writeHead(200);
res.end(`worker run pid: ${process.pid} , say hello world`);
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
cluster(集群)
cluster
依赖child_process.fork
实现,理解成自动的多次运行我们的脚本
node index.js
node index.js
node index.js
....
所以,同一份代码文件中,我们通过cluster.isMaster 或者 cluster.isPrimary
(cluster.isMaster 在源代码中被标记为Deprecated)来区分当前代码是执行在fork的进程中还是主进程中
cluster
源码
// 根据env 引用对应的模块
const childOrPrimary = 'NODE_UNIQUE_ID' in process.env ? 'child' : 'primary';
module.exports = require(`internal/cluster/${childOrPrimary}`);
所以上面的代码
// 会根据环境变量,也就是根据是否是fork执行,来确认引入哪个模块
const cluster = require('cluster');
...
primary模块
cluster.fork = function(env) {
// id 初始值 0
const id = ++ids;
// 创建worker进程
const workerProcess = createWorkerProcess(id, env);
const worker = new Worker({
id: id,
process: workerProcess
});
}
createWorkerProcess方法
function createWorkerProcess(id, env) {
...
// 调用了child_process.fork方法
return fork(cluster.settings.exec, cluster.settings.args, {
cwd: cluster.settings.cwd,
env: workerEnv,
serialization: cluster.settings.serialization,
silent: cluster.settings.silent,
windowsHide: cluster.settings.windowsHide,
execArgv: execArgv,
stdio: cluster.settings.stdio,
gid: cluster.settings.gid,
uid: cluster.settings.uid
});
}
child模块
cluster.isWorker = true;
cluster.isMaster = false; // Deprecated alias. Must be same as isPrimary.
cluster.isPrimary = false;
...