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)
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:
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()
}
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,
})
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
The wireshark will show:
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
And now the keep-alive works again.