48

I'm actually doing some load testing against an ExpressJS server, and I noticed that the response send by the server includes a "Connection: Keep-Alive" header. As far as I understand it, the connection will remain opened until the server or the client sends a "Connection: Close" header.

In some implementations, the "Connection: Keep-Alive" header comes up with a "Keep-Alive" header setting the connection timeout and the maximum number of consecutive requests send via this connection.

For example : "Keep-Alive: timeout=15, max=100"

Is there a way (and is it relevant) to set these parameters on an Express server ?

If not, do you know how ExpressJS handles this ?

Edit: After some investigations, I found out that the default timeout is set in the node standard http library:

socket.setTimeout(2 * 60 * 1000); // 2 minute timeout

In order to change this:

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end("Hello World");
}).on('connection', function(socket) {
  socket.setTimeout(10000);
}).listen(3000);

Anyway it still looks a little bit weird to me that the server doesn't send any hint to the client concerning its timeout.

Edit2: Thanks to josh3736 for his comment.

setSocketKeepAlive is not related to HTTP keep-alive. It is a TCP-level option that allows you to detect that the other end of the connection has disappeared.

Miguel L.
  • 708
  • 2
  • 7
  • 11
  • Timeout is distinct from keepAliveTimeout, socket.setTimeout cannot set the HTTP Keep-Alive timeout in a nodejs server. You should use server.keepAliveTimeout and turn TCP keepalive on at same time with using socket.setKeepAlive https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_server_keepalivetimeout. – Clocher Zhong Mar 15 '21 at 03:25

3 Answers3

38

For Express 3:

var express = require('express');
var app = express();
var server = app.listen(5001);

server.on('connection', function(socket) {
  console.log("A new connection was made by a client.");
  socket.setTimeout(30 * 1000); 
  // 30 second timeout. Change this as you see fit.
});
Community
  • 1
  • 1
dgo.a
  • 2,634
  • 23
  • 35
  • Why are you listening twice there? – gtato Jan 23 '19 at 15:06
  • Does not work for me, the timeout got overridden after I set it. Setting `keepAliveTimeout` on the Server object did work though. – Yogu Feb 05 '19 at 13:39
  • @Yogu where do you set `keepAliveTimeout`? Can you provide as another answer? – Pasupathi Rajamanickam Feb 26 '19 at 17:36
  • 4
    Why does this answer show how to do this for `express` when the question was for the base node.js `http` library? At the very least also show this for the base `http` module, even if you then go on to say "but you probably want to use express" (which some folks really don't because they need a base HTTP server purely for a protocol upgrade) – Mike 'Pomax' Kamermans Jun 08 '19 at 16:13
  • I'd love to understand what is actually going on here. What I am experiencing is when I take a really long time to process a request, eventually it looks like the request gets retried before I am finished processing the original request. – RedBullet Sep 04 '20 at 14:38
  • is this different from `app.request.setTimeout(30*1000);` ? – bvdb Sep 25 '20 at 21:42
  • Timeout is distinct from keepAliveTimeout, socket.setTimeout cannot set the HTTP Keep-Alive timeout in a nodejs server. you should use server.keepAliveTimeout https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_server_keepalivetimeout – Clocher Zhong Mar 15 '21 at 03:23
14

To set keepAliveTimeout on the express server do:

var express = require('express');
var app = express();
var server = app.listen(5001);

server.keepAliveTimeout = 30000;


Ninn
  • 141
  • 1
  • 3
10

For Node.js 10.15.2 and newer with express, only server.keepAliveTimeout was not enough. We also need to configure server.headersTimeout longer than server.keepAliveTimeout.

server.keepAliveTimeout = 30000; 
// Ensure all inactive connections are terminated by the ALB, by setting this a few seconds higher than the ALB idle timeout
server.headersTimeout = 31000; 
// Ensure the headersTimeout is set higher than the keepAliveTimeout due to this nodejs regression bug: https://github.com/nodejs/node/issues/27363

Update

Since this issue Regression issue with keep alive connections has been closed. We could just set keepAliveTimeout on the latest node.js version.


One more thing, If your node.js server is deployed under AWS ELB and encounters 502 error code occasionally.

Clients -> AWS ELB -> Node Server

AWS ELB has 60 seconds of connection idle timeout by default, and per doc

We also recommend that you configure the idle timeout of your application to be larger than the idle timeout configured for the load balancer

Config the value of keepAliveTimeout to greater than 60 seconds could be one option to eliminate this issue.

zangw
  • 43,869
  • 19
  • 177
  • 214