如何使用Express.js正确处理SIGINT?

Jac*_*ble 20 sigint node.js express

当我的Express.js服务被停止时,我需要做一些有用的事情SIGINT.使用Express.js版本3.0.6,我知道这应该工作:

var express = require('express');

var app = express();
var server = app.listen(3000);

process.on('SIGINT', function() {
  console.log('Do something useful here.');
  server.close();
});
Run Code Online (Sandbox Code Playgroud)

但是除非我发出SIGINT(Control- C)两次,否则这个过程不会给我回Bash提示符:

$ node problem.js 
^CDo something useful here.
^CDo something useful here.

net.js:1046
    throw new Error('Not running');
          ^
Error: Not running
    at Server.close (net.js:1046:11)
    at process.<anonymous> (/path/to/problem.js:8:10)
    at process.EventEmitter.emit (events.js:93:17)
    at SignalWatcher.startup.processSignalHandlers.process.on.process.addListener.w.callback (node.js:486:45)
$
Run Code Online (Sandbox Code Playgroud)

还有一点需要注意.如果我启动此Express.js服务并且不发送任何请求,SIGINT正确终止.

显然,我在这里缺少一些基本的东西?

nne*_*neo 26

通过捕获SIGINT处理程序,您将阻止默认行为,即退出进程.Ctrl+C第二次使用时,进程会因为server.close抛出未捕获的异常而死亡.

只需添加一个process.exit()SIGINT处理程序的末尾即可优雅地退出该进程.

  • 您应该清除事件循环并设置 process.exitCode 以防退出不成功,而不是调用 process.exit。 (3认同)
  • 使用 process.exit() 就像在你做了一件事后发送 ^C 一样,不应该被认为是优雅的(恕我直言)。我认为更完整的答案如下(虽然有点晚了)。 (2认同)

Kir*_*tin 8

我正在使用此代码:

server.close(() => {
  process.exit(0)
})
Run Code Online (Sandbox Code Playgroud)

  • 您应该清除事件循环并设置 process.exitCode 以防退出不成功,而不是调用 process.exit。 (2认同)

Why*_*kee 8

由于问题没有完全(或正确)回答,人们可能仍会找到这个答案,因此复活一个老人.

你问题的重要部分是:

还有一点需要注意.如果我启动此Express.js服务并且不发送任何请求,则SIGINT将正确终止.显然,我在这里缺少一些基本的东西?`

你缺少的是默认情况下express保持连接打开(HTTP keep-alive)以便重复使用.因此,当有(最近的)请求时,事件循环中仍然存在某些内容,这就是您的应用程序未关闭的原因.

使用process.exit()将工作,但就像发送另一个^ C,并可能隐藏仍然有其他东西打开的事实(例如数据库连接).当事件循环中没有任何内容时,您的应用程序应该关闭.

所以,我修改了你的例子,在连接上设置了5秒保持活动状态,以便在合理的时间内正常关闭.

var express = require('express');

var serverPort = 3000;
var app = express();
var server = app.listen(serverPort);


// HTTP Keep-Alive to a short time to allow graceful shutdown
server.on('connection', function (socket) {
  socket.setTimeout(5 * 1000);
});

// Handle ^C
process.on('SIGINT', shutdown);

// Do graceful shutdown
function shutdown() {
  console.log('graceful shutdown express');
  server.close(function () {
    console.log('closed express');
  });
}

console.log('running server: http://localhost:' + serverPort);
Run Code Online (Sandbox Code Playgroud)

  • 由于在关闭之前的长潜在延迟,这可能仍然不是理想的,并且它使得保持活动连接可能不太有用.要获得更完整的解决方案,可能需要使用优雅退出模块:https://www.npmjs.com/package/express-graceful-exit.该模块将关闭保持活动连接并等待其他活动停止,然后退出. (3认同)