1. 概述
node服务器需要重启才能执行改动后的代码,如果在生产环境中重启会造成用户几秒钟的无响应。针对这一问题,我们可以利用cluster模块来实现基于express框架的零秒热重载。
2. 原理
master进程开启一个监听重启命令的http服务器,监听重启命令后,fork一个新的工作进程,等新的工作进程创建完成时,kill原来老的工作进程,便实现了热重载。
当我需要更新项目时,使用cmd命令即可
curl http://localhost:3000/reload
pause
该脚本可以配合supervisor一起使用,守护进程。
supervisor -w startServer.js startServer.js
3. 源码
const cluster = require('cluster');
const child_process = require('child_process');
const http = require('http');
if (cluster.isMaster) {
console.log(`主进程 ${process.pid} 正在运行`);
// fork工作进程
forkWorkProcess();
createReloadServer();
cluster.on('exit', work => {
console.log(`工作进程 ${work.process.pid} 已退出`);
});
} else {
// express框架的启动文件
require('./bin/www');
console.log(`工作进程 ${process.pid} 已启动`);
}
// 创建1个工作进程
function forkWorkProcess() {
child_process.exec('nvm use 8.12 64', (e, stdout) => {
console.log(stdout);
setTimeout(() => {
cluster.fork();
}, 2000);
});
}
// 创建监听重启命令的http服务器
function createReloadServer() {
http.createServer((req, res) => {
if (req.url === '/reload') {
if (cluster.isMaster) {
const arr = Object.keys(cluster.workers);
if (arr.length !== 0) {
forkWorkProcess();
setTimeout(() => {
const arr = Object.keys(cluster.workers);
process.kill(cluster.workers[arr[0]].process.pid);
}, 20000);
}
}
res.end('reloading');
} else {
res.end('unknow command');
}
}).listen(3000);
}
// 查看log
setInterval(() => {
if (cluster.isMaster) {
const workerArr = Object.keys(cluster.workers);
// 工作进程意外退出时,fork新的工作进程
if (workerArr.length === 0) {
forkWorkProcess();
}
console.log(new Date());
console.log(workerArr);
}
}, 10000);