如何正常重启NodeJS服务器?

时间:2012-01-19 21:59:57

标签: node.js cluster-computing restart

目前,我的侧面项目的prod环境是一个git repo,我在其中输入一些代码,用Ctrl-C手动终止服务器,然后手动重启。

我意识到这有很多问题。例如,如果用户仍然处于重要事情的中间并且该过程正在处理敏感数据,那么我刚刚杀了它?!

当我使用node v0.4.x时,有一个很好的Cluster模块可以在应用程序处于安静状态时正常重启服务器。在v0.6.x中,Cluster模块内置于节点中,但它确实非常简单,并且没有优雅的重启能力。

任何人都知道如何在v0.6.x中优雅地重启nodejs服务器?

3 个答案:

答案 0 :(得分:16)

您可以在节点代码中处理POSIX信号。

参见示例代码,它将处理SIGINT(例如Ctrl-C)作为所有集群工作者的STOP信号,SIGUSR2将只重新启动所有工作程序

因此,发出kill -SIGUSR2 PID,其中PID是节点主PID将重启所有集群

module.exports = function(app) {
    var cluster = require('cluster');
    var numCPUs = require('os').cpus().length;
    var workerList = new Array();
    var sigkill = false;

    if (cluster.isMaster) {
        for (var i = 0; i < numCPUs; i++) {
            var env = process.env;
            var worker = cluster.fork(env);
            workerList.push(worker);
        }

        process.on('SIGUSR2',function(){
            console.log("Received SIGUSR2 from system");
            console.log("There are " + workerList.length + " workers running");
            workerList.forEach(function(worker){
                console.log("Sending STOP message to worker PID=" + worker.pid);
                worker.send({cmd: "stop"});
            });
        });

        process.on('SIGINT',function(){
            sigkill = true;
            process.exit();
        });

        cluster.on('death', function(worker) {
            if (sigkill) {
                logger.warn("SIGKINT received - not respawning workers");
                return;
            }
            var newWorker = cluster.fork();
            console.log('Worker ' + worker.pid + ' died and it will be re-spawned');

            removeWorkerFromListByPID(worker.pid);
            workerList.push(newWorker);
        });
    } else {
        process.on('message', function(msg) {
            if (msg.cmd && msg.cmd == 'stop') {
                console.log("Received STOP signal from master");
                app.close();
                process.exit();
            }
        });
        app.listen(3000);
    }

    function removeWorkerFromListByPID(pid) {
        var counter = -1;
        workerList.forEach(function(worker){
            ++counter;
            if (worker.pid === pid) {
                workerList.splice(counter, 1);
            }
        });
    }
}

答案 1 :(得分:2)

有一个名为Forever的模块。

可以优雅地重启该过程。我想你可以以某种方式运行多个集群实例(每个核心一个)并使用Forever监控/重启它们。

这只是我找到的一个选项;我愿意接受建议!

答案 2 :(得分:1)

还有一个名为PM2的模块。它能够停止集群中的所有进程。