How to enable keep-alive for http/https?

81 views
Skip to first unread message

James Coglan

unread,
Aug 27, 2014, 4:46:40 PM8/27/14
to Node list
I'm trying to figure out how HTTP keep-alive works. According to the docs, all requests by default use the global http.Agent (or https.Agent), which pools connections per origin. Consider the following code; it starts a TCP server that provides a basic response to HTTP requests and does not close the socket.

```
var http = require('http'),
    net  = require('net');

net.createServer(function(conn) {
  console.log('[CONNECT]');

  conn.on('data', function(chunk) {
    console.log(chunk.toString());
    conn.write( 'HTTP/1.1 200 OK\r\n' +
                'Content-Length: 5\r\n' +
                'Connection: keep-alive\r\n' +
                '\r\n' +
                'Hello');
  });
}).listen(4000);

var origin = 'http://localhost:4000'

http.get(origin + '/first', function(response) {
  response.on('data', function() { });

  response.on('end', function() {
    http.get(origin + '/third', function(response) { });
  });
});

http.get(origin + '/second', function(response) { });
```

The 'first' and 'second' and requests want to happen in parallel, so I would expect them to use separate TCP connections, and indeed they do. However, the 'third' request, which happens once 'first' is complete, is sent over its own TCP connection rather than reusing the one used for 'first'.

Is it possible to make sequential requests reuse the TCP connection, and if so how?

Many thanks,
James

--
James Coglan
http://jcoglan.com
+44 (0) 7771512510

// ravi

unread,
Aug 27, 2014, 10:14:20 PM8/27/14
to nod...@googlegroups.com
On Aug 27, 2014, at 4:40 PM, James Coglan <jco...@gmail.com> wrote:
I'm trying to figure out how HTTP keep-alive works. According to the docs, all requests by default use the global http.Agent (or https.Agent), which pools connections per origin. Consider the following code; it starts a TCP server that provides a basic response to HTTP requests and does not close the socket.


Hello James,

I do not know how well your TCP server code would work in certain scenarios (e.g: when there is more than one chunk of request data, which, if I am reading your code right, will cause a situation where a response is sent by you before the end of the request), but w.r.t http.Agent and keep-alives, you might find Issue 4769 an interesting read (and my own comments, perhaps: https://github.com/joyent/node/issues/4769#issuecomment-53116476). In your case you are sending your third request when the response to the first ends, which means (most likely) that after you fired the first and second request, there was no request pending, which IIUC causes http.Agent to close open keep-alive sockets.

—ravi

James Coglan

unread,
Aug 28, 2014, 5:13:05 PM8/28/14
to Node list
On 27 August 2014 21:58, // ravi <ravi-...@g8o.net> wrote:
On Aug 27, 2014, at 4:40 PM, James Coglan <jco...@gmail.com> wrote:
I'm trying to figure out how HTTP keep-alive works. According to the docs, all requests by default use the global http.Agent (or https.Agent), which pools connections per origin. Consider the following code; it starts a TCP server that provides a basic response to HTTP requests and does not close the socket.

I do not know how well your TCP server code would work in certain scenarios (e.g: when there is more than one chunk of request data, which, if I am reading your code right, will cause a situation where a response is sent by you before the end of the request),

I know, it was just a quick hack to see what the HTTP client was doing at the TCP level.
 
but w.r.t http.Agent and keep-alives, you might find Issue 4769 an interesting read (and my own comments, perhaps: https://github.com/joyent/node/issues/4769#issuecomment-53116476). In your case you are sending your third request when the response to the first ends, which means (most likely) that after you fired the first and second request, there was no request pending, which IIUC causes http.Agent to close open keep-alive sockets.

That's what I suspected, but if it can't reuse a connection for concurrent requests, and won't reuse them for immediately sequential requests (which is the scenario I have in production), then when *does* it reuse connections? 

// ravi

unread,
Aug 28, 2014, 11:36:15 PM8/28/14
to nod...@googlegroups.com
On Aug 28, 2014, at 3:35 AM, James Coglan <jco...@gmail.com> wrote:
>
>> but w.r.t http.Agent and keep-alives, you might find Issue 4769 an interesting read (and my own comments, perhaps: https://github.com/joyent/node/issues/4769#issuecomment-53116476). In your case you are sending your third request when the response to the first ends, which means (most likely) that after you fired the first and second request, there was no request pending, which IIUC causes http.Agent to close open keep-alive sockets.
>
> That's what I suspected, but if it can't reuse a connection for concurrent requests, and won't reuse them for immediately sequential requests (which is the scenario I have in production), then when *does* it reuse connections?


Indeed!

I suppose it will reuse a connection (unfortunately called a ‘socket’) when both conditions are true: the pool max (for that target host) has been reached and all connections are in use. In this case, the new request will be queued and when a response arrives on a connection, the new request will be dequeued and sent down that open connection.

The above is my understanding, but I could be wrong.

—ravi

Reply all
Reply to author
Forward
0 new messages