这是基于我自己收集到的。
HTTP 标头 Keep-Alive: timeout=5, max=1000 只是随 HTTP 请求一起发送的标头。将其视为在两个主机(客户端和服务器)之间进行通信的一种方式。主持人说“嘿,请保持连接活跃”。这对于现代浏览器来说是自动的,服务器可能会实现它,也可能不会。代理的keepAlive: true 就像documentation 所说的那样
不要与 Connection 标头的 keep-alive 值混淆。
这意味着keepAlive: false != Connection: close。它实际上与标题无关。代理将在 TCP 级别使用套接字等在 HTTP 客户端上处理事情。
keepAlive boolean 即使没有未完成的请求也可以保留套接字,以便它们可以用于将来的请求,而无需重新建立 TCP 连接
只要您为 HTTP 客户端使用代理,就会使用 Connection: Keep-Alive。 除非 keepAlive 设置为 false 和 maxSockets 设置为 Infinity。
const options = {
port: 3000,
agent: new http.Agent({
keepAlive: false ,
maxSockets: Infinity,
})
};//----> Connection: close
agent 到底是什么?
代理负责管理 HTTP 客户端的连接持久性和重用。它为给定的主机和端口维护一个待处理请求的队列,为每个请求重用一个套接字连接,直到队列为空,此时套接字要么被销毁,要么被放入一个池中,以便再次用于请求到相同的主机和端口。是销毁还是池化取决于 keepAlive 选项。
池中的连接为它们启用了 TCP Keep-Alive,但服务器可能仍会关闭空闲连接,在这种情况下,它们将从池中删除,并且当对该主机发出新的 HTTP 请求时将建立新的连接,并且港口。服务器也可能拒绝允许同一连接上的多个请求,在这种情况下,必须为每个请求重新建立连接,并且不能被池化。代理仍会向该服务器发出请求,但每个请求都将通过新连接发生。
关于 timeout 和 max,据我所知,这些是在为 Apache 添加配置时设置的(自动?)
#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive On
#
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
#
MaxKeepAliveRequests 100
#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 5
给了
Connection:Keep-Alive
Keep-Alive:timeout=5, max=100
但是这些与 NodeJS 无关?我会让更多经验丰富的人回答这个问题。无论如何,代理不会设置这些并且不会修改Connection: Keep-Alive,除非如上所述将keepAlive 设置为false 和maxSockets 为Infinity。
但是,要使代理配置具有任何意义,Connection 必须设置为 Keep-Alive。
好的,现在来做一个小实验,看看代理的工作情况!
我已经设置了一个客户端进行测试(因为axios 使用http.agent 作为代理,我只使用http)。
const http = require('http');
const options = {
port: 3000,
agent: new http.Agent({
keepAlive: true,
maxSockets: 2,
}),
// headers: {
// 'Connection': 'close'
// }
};
var i = 0;
function request() {
console.log(`${++i} - making a request`);
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
req.end();
}
setInterval(function(){ request(); }, 3000); // send a request every 3 seconds
服务器是一个快速应用程序(我将跳过细节)
server.on('connection', function(socket) {
socket.id = shortid.generate();
//socket.setTimeout(500)
console.log("A new connection was made by a client." + ` SOCKET ${ socket.id }`);
socket.on('end', function() {
console.log(`SOCKET ${ socket.id } END: other end of the socket sends a FIN packet`);
});
socket.on('timeout', function() {
console.log(`SOCKET ${ socket.id } TIMEOUT`);
});
socket.on('error', function(error) {
console.log(`SOCKET ${ socket.id } ERROR: ` + JSON.stringify(error));
});
socket.on('close', function(had_error) {
console.log(`SOCKET ${ socket.id } CLOSED. IT WAS ERROR: ` + had_error);
});
});
为了让您看到 keepAlive: false != Connection: close,请将 keepAlive 设置为 false 并查看服务器端发生的情况。
agent: new http.Agent({
keepAlive: false,
maxSockets: 20
})
服务器
客户
如您所见,我没有将 maxSockets 设置为 Infinity,因此即使代理中的 keepAlive 设置为 false,Connection 标头也设置为 Keep-Alive。但是,每次向服务器发送请求时,服务器上的套接字在每次请求后立即关闭。让我们看看当我们将 keepAlive 设置为 true 时会发生什么。
服务器
客户
这一次,只使用了一个套接字。客户端和服务器之间存在持久连接,该连接持续超过单个请求。
感谢great article,我学到的一件事是,在 Firefox 上,您一次可以拥有多达 6 个并发持久连接。您可以通过将 maxSockets 设置为 6 来使用代理重现此情况。出于测试目的,我将其设置为 2。此外,我不会从服务器返回任何内容,因此连接将处于挂起状态。
agent: new http.Agent({
keepAlive: true,
maxSockets: 2,
}),
//res.send('response from the server');
服务器
客户
客户端不断发送请求,但服务器只收到两个请求。然而两分钟后,看到http_server_timeout
在假定套接字超时之前不活动的毫秒数。
接受两个新请求。实际上,客户端已经将后续请求排队,一旦服务器释放了套接字,客户端就可以从队列中发送两个新请求。
所以,我希望这会有所帮助。