node.js - ¿Cómo manejar adecuadamente SIGINT con Express.js?
(3)
Al capturar el controlador SIGINT
, está evitando el comportamiento predeterminado , que consiste en abandonar el proceso. Cuando utiliza Ctrl+C
la segunda vez, el proceso muere porque server.close
lanza una excepción no detectada.
Simplemente agregue un process.exit()
al final de su controlador SIGINT
para salir del proceso con gracia.
Necesito hacer algunas cosas útiles cuando SIGINT
detiene mi servicio Express.js . Al usar Express.js versión 3.0.6, entiendo que esto debería funcionar:
var express = require(''express'');
var app = express();
var server = app.listen(3000);
process.on(''SIGINT'', function() {
console.log(''Do something useful here.'');
server.close();
});
Pero el proceso no me devuelve el aviso de Bash a menos que SIGINT
( Control - C ) dos veces:
$ 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)
$
Una advertencia más. Si inicio este servicio Express.js y no envío ninguna solicitud, entonces SIGINT
termina correctamente.
Claramente hay algo fundamental que me estoy perdiendo aquí?
Estoy usando este código:
server.close(() => {
process.exit(0)
})
Resucitar a un antiguo puesto que la pregunta no se ha respondido completamente (o correctamente) y las personas aún pueden encontrar esta respuesta.
La parte importante de tu pregunta es:
Una advertencia más. Si inicio este servicio Express.js y no envío ninguna solicitud, entonces SIGINT termina correctamente. Claramente hay algo fundamental que me estoy perdiendo aquí?
Lo que falta es que, de forma predeterminada, Express mantenga las conexiones abiertas (HTTP keep-alive) para su reutilización. Entonces, cuando ha habido una solicitud (reciente) todavía hay algo en el ciclo de eventos y esa es la razón por la que su aplicación no se está cerrando.
El uso de process.exit()
funcionará, pero es como enviar otra ^ C, y puede ocultar el hecho de que todavía hay algo más abierto (por ejemplo, conexiones de base de datos). Su aplicación debería cerrarse cuando no quede nada en el ciclo de eventos.
Por lo tanto, modifiqué su ejemplo, estableciendo una vida útil de 5 segundos en la conexión para que se pueda cerrar con gracia en un tiempo razonable.
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);