🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
第二次迭代之后,服务器本身的功能和性能已经得到了初步满足。接下来我们需要从稳定性的角度重新审视一下代码,看看还需要做些什么。 ## 设计 从工程角度上讲,没有绝对可靠的系统。即使第二次迭代的代码经过反复检查后能确保没有bug,也很难说是否会因为NodeJS本身,或者是操作系统本身,甚至是硬件本身导致我们的服务器程序在某一天挂掉。因此一般生产环境下的服务器程序都配有一个守护进程,在服务挂掉的时候立即重启服务。一般守护进程的代码会远比服务进程的代码简单,从概率上可以保证守护进程更难挂掉。如果再做得严谨一些,甚至守护进程自身可以在自己挂掉时重启自己,从而实现双保险。 因此在本次迭代时,我们先利用NodeJS的进程管理机制,将守护进程作为父进程,将服务器程序作为子进程,并让父进程监控子进程的运行状态,在其异常退出时重启子进程。 ## 实现 根据以上设计,我们编写了守护进程需要的代码。 ~~~ var cp = require('child_process'); var worker; function spawn(server, config) { worker = cp.spawn('node', [ server, config ]); worker.on('exit', function (code) { if (code !== 0) { spawn(server, config); } }); } function main(argv) { spawn('server.js', argv[0]); process.on('SIGTERM', function () { worker.kill(); process.exit(0); }); } main(process.argv.slice(2)); ~~~ 此外,服务器代码本身的入口函数也要做以下调整。 ~~~ function main(argv) { var config = JSON.parse(fs.readFileSync(argv[0], 'utf-8')), root = config.root || '.', port = config.port || 80, server; server = http.createServer(function (request, response) { ... }).listen(port); process.on('SIGTERM', function () { server.close(function () { process.exit(0); }); }); } ~~~ 我们可以把守护进程的代码保存为`daemon.js`,之后我们可以通过`node daemon.js config.json`启动服务,而守护进程会进一步启动和监控服务器进程。此外,为了能够正常终止服务,我们让守护进程在接收到`SIGTERM`信号时终止服务器进程。而在服务器进程这一端,同样在收到`SIGTERM`信号时先停掉HTTP服务再正常退出。至此,我们的服务器程序就靠谱很多了。