DEV Community

ayou
ayou

Posted on • Edited on

3 1 1 1 1

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.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Postgres on Neon - Get the Free Plan

No credit card required. The database you love, on a serverless platform designed to help you build faster.

Get Postgres on Neon

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay