问题描述
我正在使用
客户
如您所见,我没有将maxSockets设置为Infinity,因此即使代理中的keepAlive设置为false,Connection头也设置为Keep-Alive.但是,每次将请求发送到服务器时,每个请求后都会立即关闭服务器上的套接字.让我们看看将keepAlive设置为true会发生什么情况.
服务器
客户
这一次,仅使用了一个插槽.客户端和服务器之间存在持久连接,并且该连接超出了单个请求.
由于
客户
客户端继续发送请求,但服务器仅接收到两个请求.两分钟后,请参见 http_server_timeout
两个新请求被接受.实际上,客户端已经将后续请求排队,一旦服务器释放了套接字,客户端就可以从队列中发送两个新请求.
所以,我希望这会有所帮助.
I'm using axios to make HTTP requests.
axios offers the option to specify new http.Agent()
in the request config when used in Node.
The http Agent options are:
const agentOptions = {
keepAlive: true, // Keep sockets around even when there are no outstanding requests, so they can be used for future requests without having to reestablish a TCP connection. Defaults to false
keepAliveMsecs: 1000, // When using the keepAlive option, specifies the initial delay for TCP Keep-Alive packets. Ignored when the keepAlive option is false or undefined. Defaults to 1000.
maxSockets: Infinity, // Maximum number of sockets to allow per host. Defaults to Infinity.
maxFreeSockets: 256 // Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Defaults to 256.
}
There is also the HTTP header with timeout
and max
options.
The options don't seem to line up (keepAliveMsecs
, maxSockets
and maxFreeSockets
vs timeout
and max
), which suggests they are different.
What's the difference between Node's new Agent({ keepAlive: true })
and the HTTP header Keep-Alive: timeout=5, max=1000
..?
This is based on what I've gathered myself.
The HTTP header Keep-Alive: timeout=5, max=1000
is just a header sent with HTTP requests. See it as a way to communicate between two hosts (client and server). The host says 'hey keep the connection alive please'. This is automatic for modern browsers and servers might implement it or not. The keepAlive: true
of the agent is as the documentation says
What that means is that keepAlive: false
!= Connection: close
. It doesn't really have anything to do with the header. The agent will take care of things at the TCP level with sockets and such on the HTTP client.
As soon as you use an agent for your HTTP client, the Connection: Keep-Alive
will be used. Unless keepAlive
is set to false
and maxSockets
to Infinity
.
const options = {
port: 3000,
agent: new http.Agent({
keepAlive: false ,
maxSockets: Infinity,
})
};//----> Connection: close
What exactly is an agent?
Regarding timeout and max, as far as I know, these are set (automatically?) when adding config for 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
which gives
Connection:Keep-Alive
Keep-Alive:timeout=5, max=100
But these are irrelevant for NodeJS? I'll let more experimented people answer this. Anyway, the agent won't set these and won't modify Connection: Keep-Alive
unless setting keepAlive
to false
and maxSockets
to Infinity
as said above.
However, for the agent config to have any meaning, Connection
must be set to Keep-Alive
.
Okay, now for a little experiment to see the agent at work!
I've set up a client for testing (since axios
use http.agent
for the agent anyway, I just use 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
And the server is an express application (I'll skip the details)
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);
});
});
To make you see that keepAlive: false
!= Connection: close
, let set keepAlive to false and see what happens server-side.
agent: new http.Agent({
keepAlive: false,
maxSockets: 20
})
Server
Client
As you can see, I've not set maxSockets to Infinity so even though keepAlive in the agent was set to false, the Connection header was set to Keep-Alive. However, each time a request was sent to the server, the socket on the server was immediately closed after each request. Let's see what happens when we set keepAlive to true.
Server
Client
This time around, only one socket have been used. There was a persistent connection between the client and the server that persisted beyond a single request.
One thing I've learned, thanks to this great article is that on Firefox, you can have as many as 6 concurrent persistent connections at a time. And you can reproduce this with the agent by setting maxSockets to 6. For testing purposes, I'll set this to 2. And also, I won't return anything from the server so the connection will be left hanging.
agent: new http.Agent({
keepAlive: true,
maxSockets: 2,
}),
//res.send('response from the server');
Server
Client
The client keeps sending requests but only two have been received by the server. Yet after two minutes, see http_server_timeout
two new requests are accepted. Actually, the client has queued the subsequent requests and once the server freed the sockets, the client was able to send two new requests from the queue.
So, I hope this helps.
这篇关于NodeJS new Agent()和HTTP Keep-Alive标头之间的区别..?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!