Scenario: a Nodejs rest API using http.createServer()
Goal: When a SIGNINT
comes (in my case from PM2 reload) do a graceful shutdown of the server and then shutdown the DB connection and then exit peacefully.
Code:
// index.js
server.keepAliveTimeout = 10
process.on('SIGINT', () => {
server.close(err => {
// close the DB
...
process.exit(0)
})
})
// the code related to any API response
const headers = {
...
'Connection': 'close'
}
response.writeHead(statusCode, headers)
return response.end(JSON.stringify(data))
Problem: The server.close
callback never fires. The PM2 process hits the timeout after (in my case) 20 seconds and so the shutdown is not graceful anymore.
Investigated reason: The callback is fired nicely if NO browser connections are open (e.g. if no one calls the API) or if the API call is made with Firefox. With Chrome instead, I can see in chrome://net-internals/#sockets
1 idle transport_socket_pool after firing a request. In this case the close
callback does not fire. As soon as I clear the idle sockets in Chrome the callback fires properly. Note that in Chrome's incognito mode the socket is not kept idle but closed properly, so the callback fires.
Questions:
- Is it this a bug in Chrome or a normal behavior?
- Shouldn't the header
Connection: close
and the shortkeepAliveTimeout
be enough to notify any client that they should not keep any socket open for so long? - Which is the proper way to handle clients that prevents
server.close
to complete? - Shall I loop through all the created sockets and close them manually?