azangru
azangru

Reputation: 2738

Can’t gracefully shut down a node + Express app (node http server's close function does not complete)

I want the Express.js-based server of the app I am working on to properly close all connections before exiting the node process when a shutdown signal (SIGTERM or SIGINT) is sent.

I have slightly modified the express-graceful-shutdown middleware (which is really simple), so the relevant part of my code looks approximately as follows:

server.js

import gracefulShutdown from './tools/graceful-shutdown';

const server = app.listen(config.port, () => {
  console.log(`Server is running`);
});

app.use(gracefulShutdown(server));

graceful-shutdown.js:

function gracefulShutdownMiddleware(server) {

  let shuttingDown = false;
  const forceTimeout = 10 * 1000; // giving the app 10 seconds to shutdown gracefully


  process.on('SIGTERM', gracefulExit); // listen for TERM signal (e.g. kill)
  process.on ('SIGINT', gracefulExit); // listen for INT signal (e.g. Ctrl-C)

  function gracefulExit() {

    if (shuttingDown) return;
    shuttingDown = true;
    console.log('Received kill signal (SIGTERM), shutting down');

    setTimeout(function () {
      console.log('Could not close connections in time, forcefully shutting down');
      process.exit(1);
    }, forceTimeout);

    server.close(function () {
      console.log('Closed out remaining connections.');
      process.exit();
    });

  }

  function middleware(req, res, next) {
    if (!shuttingDown) return next()
    res.set('Connection', 'close')
    res.status(503).send('Server is in the process of restarting.')
  }

  return middleware

}

export default gracefulShutdownMiddleware;

The problem I am observing is this. If I shut down the node server immediately after it starts, it shuts down as expected (function gracefulExit in the middleware works correctly, server.close executes fine, and the callback to server.close prints out the console message). If, however, I open the browser and actually visit my app on the localhost, so that the server has some work to do, and then try to shut the server down, the server.close function does not seem to finish (so it never calls the callback with process.exit until finally the setTimeout calls its own callback and forcefully shuts down the app.

The server.close function is this function from node’s lib.

Could you help me figure out why node server’s close function may fail to complete?

Upvotes: 0

Views: 2447

Answers (1)

robertklep
robertklep

Reputation: 203231

.close() doesn't actually close any active connections, it will only stop new connections from being made, and it'll wait for the active connections to get closed (by the client).

If clients are connected that keep a connection open (say using a keep-alive connection), the callback may never get called.

There's a package called http-shutdown that will help with gracefully shutting down an HTTP server.

Upvotes: 1

Related Questions