DEV Community

ayou
ayou

Posted on • Updated on

To request with keep-alive using HTTP agent in Node.js

Request without Keep-Alive

As we all know that in browsers, multi HTTP requests can resue a TCP connection with the HTTP header "connection: keep-alive;". But how to do in Node.js?

For example, here is a simple code snippet of requesting in Node.js:

// server.js
const http = require('http')

http
  .createServer((req, res) => {
    res.writeHead(200)
    res.end('Hello World')
  })
  .listen(3000)

// client.js
const http = require('http')

function request() {
  http
    .request(
      {
        host: 'localhost',
        port: 3000,
        pathname: '/',
      },
      (res) => {
        let buffer = []
        res.on('data', (chunk) => {
          buffer.push(chunk)
        })
        res.on('end', () => {
          console.log(buffer.toString())
        })
      }
    )
    .end()
}

request()

setTimeout(() => {
  request()
}, 1000)
Enter fullscreen mode Exit fullscreen mode

When using wireshark to debug, we can find that the client port of two requets is different and there are two "Three-way Handshake" processes:

Image description

Request with Keep-Alive using http.Agent

Now, let's request with keep-alive using http.Agent, we only need to add a short piece of code:

const agent = new http.Agent({
  keepAlive: true,
})

function request() {
  http
    .request(
      {
        agent,
        host: 'localhost',
        port: 3000,
        pathname: '/',
      },
      () => {
        // ...
      }
    )
    .end()
}
Enter fullscreen mode Exit fullscreen mode

But, the result of wireshark won't change! Actually, we need to specify the maxSockets of the agent:

const agent = new http.Agent({
  keepAlive: true,
  maxSockets: 1,
})
Enter fullscreen mode Exit fullscreen mode

Image description

Why? Because maxSockets indicats the max TCP connections that can be established per host. And the default value is Infinity. If we don't set its value, a new connection will always be established for every request.

Now, let's change our code a little:

setTimeout(() => {
  request()
}, 10000) // 1000 -> 10000
Enter fullscreen mode Exit fullscreen mode

The wireshark will show:

Image description

The keep-alive didn't work again! And we can see that the server send a FIN packet in about 5s. So is there any parameter for server to control the timeout? Yes, that is keepAliveTimeout,let's set it to 10s:

const http = require('http')

const server = http
  .createServer((req, res) => {
    res.writeHead(200)
    res.end('Hello World')
  })
  .listen(3000)

server.keepAliveTimeout = 10000
Enter fullscreen mode Exit fullscreen mode

And now the keep-alive works again.

Top comments (0)