前言:放假在家阅读了
cfork
模块的源码,发现其中的进程重启管理很有意思,值得学习,模仿该功能自己写了简单的进程fork和refork的核心代码片段
- 启动多进程
- 子进程退出自动fork新进程
./fork.js
const cluster = require('cluster');
const os = require('os');
const cupCount = os.cpus().length;
module.exports = fork;
/**
* @name {Function} frok
* @param {Object} options
* - {String} exec [必填]进程文件
* - {Array} args [必填]进程命令参数
* - {Boolean} silent 是否要发送输 默认false
* - {Number} count, 进程数量 默认为CPU核数
* - {Boolean} refork, 当work进程退出或者断开,是否需要重启, 默认是true
*/
function fork (options = {}) {
if (cluster.isWorker) {
return;
}
if( !options.exec ) {
return;
}
const totalWorkerCount = options.count > 0 ? options.count : cupCount;
let opts = {
exec: options.exec
};
let newWorker;
let workerCount = 0;
// 启动主进程
cluster.setupMaster(opts);
for( let i=0; i<totalWorkerCount; i++ ) {
// 根据配置启动相关的子进程
newWorker = forkWorker();
}
/**
* @name forkWorker worker进程启动方法
* @return {Object}
*/
function forkWorker() {
// 判断进程是否超过CPU数量
if( workerCount >= cupCount ) {
return;
}
// 如果不超过CPU数量的就fork worker进程
workerCount ++;
return cluster.fork();
}
/**
* @name reforkWorker worker进程重启方法
* @return {Object}
*/
function reforkWorker() {
return forkWorker()
}
// 监听进程是否退出
cluster.on('exit', (worker, code, signal) => {
console.log( `the worker pid ${worker.process.pid} has exited` )
// 重新fork进程
reforkWorker();
});
// 监听进程是否断开连接
cluster.on('disconnect', (worker) => {
console.log( `the worker pid ${worker.process.pid} has disconnected` )
let isDead = worker.isDead && worker.isDead();
if ( isDead ) {
console.log( `the worker pid ${worker.process.pid} is dead` )
return;
}
workerCount --;
reforkWorker();
});
return cluster;
}
index.js
const fork = require('./fork');
fork({
exec: './worker'
})
worker.js
const http = require('http');
const process = require('process');
const PORT = 3001;
const server = http.createServer((req, res) => {
res.write('hello fork');
res.end();
});
server.listen(PORT, () => {
console.log(`the server is start at port ${PORT}, PID=${process.pid}`)
})
可以看出当监听到子进程退出后,就会自动重启一个新的进程,保证指定数量多进程的执行