如何在未捕获的异常上正常重启NodeJS服务器?

时间:2015-06-02 06:38:37

标签: node.js azure iis express

我正在使用the express-domain-middleware模块将我的请求包装在域中。在我的错误中间件中,我有以下检查:

if(err.domain) {
 //something should happen here, it's completely uncaught
}
else {
 //silly kids, I'll log this and send a 500;

以上代码段基于express-domain-middleware文档中的此示例:

//with domain-middleware
app.use(require('express-domain-middleware'));
app.use(app.router);

app.use(function errorHandler(err, req, res, next) {
 console.log('error on request %d %s %s', process.domain.id, req.method, req.url);
 console.log(err.stack);
 res.send(500, "Something bad happened. :(");

 if(err.domain) {
  //you should think about gracefully stopping & respawning your server
  //since an unhandled error might put your application into an unknown state
 }
});

app.get('/error', function(req, res, next) {
 db.query('SELECT happiness()', process.domain.intercept(function(rows) {
  fs.readFile('asldkfjasdf', process.domain.intercept(function(contents) {
    process.nextTick(process.domain.intercept(function() {
      throw new Error("The individual request will be passed to the express error handler, and your application will keep running.");
   }));
  }));
 }));
});

如果在域外发生此异常,我不想做的就是调用process.exit(1)(我认为没有人会这样做,对吧?)。我也不想让我的应用程序处于危险状态。我宁愿只记录未捕获的异常,以便稍后重构它,优雅地重新启动这个域(服务器?),然后继续讨论。

假设

  1. 通过采用这种方法,较大的应用程序不会受到一个域的不稳定性的影响。我可以重新启动而不会终止任何其他连接。 (编辑:我创建了一个路由,它会故意抛出未处理的异常并在单独的选项卡中登录到应用程序。通过强制异常和Forever重启,我也杀死了'合法'会话 - 我猜我做错了什么。)
  2. 如果我只是重新启动服务器,用户将不知道发生了什么。我假设他们只是在刷新后才会看到登录屏幕,而不知道为什么。如果这是一个已处理的异常,我会向客户端发送一个JSON响应,说明发生了什么或将用户重定向到错误页面。当未处理异常时,处理此方案的正确方法是什么?
  3. TLDR;

    • 此应用程序在IIS上的Azure中运行。我发送了什么命令,以便应用程序正常重启?我不熟悉IIS将对Forever采取什么行为。我有目的地使用Forever在本地启动应用程序并观察它在强制执行未处理的异常时自动重启 - 但我在Mac上开发并且应用程序在Windows上运行。需要Windows解决方案=)

    修改编辑如果有误解,请更正我,我不知道域内发生的事情和未捕获的异常。我在这里学习!!

1 个答案:

答案 0 :(得分:0)

节点程序可以在spawn:

的帮助下重启自己
var exec = require('child_process').exec;

spawn('sh', ['-c', 'sleep 2; node /home/username/Desktop/MainNodeApplication.js'], {
        detached: true,
        stdio: ['ignore', 'ignore', 'ignore']
    });

process.exit(0);

以前的代码是为在Linux机器上运行而编写的,其中一个非常简单的节点脚本存储在/home/username/Desktop/MainNodeApplication.js中。此代码生成另一个进程,将其与父进程分离,然后立即退出。同时,生成的进程在2秒内重新启动节点脚本,在我们完好后确定其他实例有时间关闭。

这并不能让您一路走到您想要的地方,但它可以让您优雅地重启您的代码。您可以在启动时传递参数,以便让它更好地了解它应该出现的状态,或者将错误信息传递给用户。您可以通过在spawn参数中为节点调用添加参数来实现此目的。