NodeJS new Agent() 和 HTTP Keep-Alive 标头之间的区别..? [英] Difference between NodeJS new Agent() and HTTP Keep-Alive header..?

查看:16
本文介绍了NodeJS new Agent() 和 HTTP Keep-Alive 标头之间的区别..?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用

客户

如您所见,我没有将 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

Not to be confused with the keep-alive value of the Connection header.

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.

keepAlive boolean 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

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?

An Agent is responsible for managing connection persistence and reuse for HTTP clients. It maintains a queue of pending requests for a given host and port, reusing a single socket connection for each until the queue is empty, at which time the socket is either destroyed or put into a pool where it is kept to be used again for requests to the same host and port. Whether it is destroyed or pooled depends on the keepAlive option.

Pooled connections have TCP Keep-Alive enabled for them, but servers may still close idle connections, in which case they will be removed from the pool and a new connection will be made when a new HTTP request is made for that host and port. Servers may also refuse to allow multiple requests over the same connection, in which case the connection will have to be remade for every request and cannot be pooled. The Agent will still make the requests to that server, but each one will occur over a new connection.

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

The number of milliseconds of inactivity before a socket is presumed to have timed out.

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 标头之间的区别..?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆