node.js - NodeJS new Agent()和HTTP Keep-Alive header 之间的区别..?

标签 node.js axios keep-alive

我正在使用axios发出HTTP请求。

当在Node中使用axios时,可以在request config中指定new http.Agent()的选项。

http Agent选项是:

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.
}

还有带有timeoutmax选项的HTTP header

选项似乎没有对齐(keepAliveMsecsmaxSocketsmaxFreeSocketstimeoutmax),这表明它们是不同的。

Node的new Agent({ keepAlive: true })和HTTP header Keep-Alive: timeout=5, max=1000 ..有什么区别?

最佳答案

这是基于我自己收集的信息。
HTTP header Keep-Alive: timeout=5, max=1000只是随HTTP请求发送的 header 。将其视为在两个主机(客户端和服务器)之间进行通信的一种方式。主持人说:“嘿,请保持连接活跃”。这对于现代浏览器是自动的,服务器可能会实现也可能不会实现。代理的keepAlive: true就像documentation所说的

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


这意味着keepAlive: false!= Connection: close。它实际上与标题没有任何关系。该代理将使用套接字以及HTTP客户端上的来处理TCP级别的事务。

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


一旦为HTTP客户端使用代理,就会使用Connection: Keep-Alive除非将 keepAlive设置为false,并且将maxSockets设置为Infinity
const options = {
  port: 3000,
  agent: new http.Agent({ 
        keepAlive: false ,
        maxSockets: Infinity,
    })
};//----> Connection: close
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.


关于超时 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无论如何都使用agent的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
    })
服务器
enter image description here
客户
enter image description here
如您所见,我没有将maxSockets设置为Infinity,因此即使代理中的keepAlive设置为false,Connection头设置为Keep-Alive。但是,每次将请求发送到服务器时,每个请求后都会立即关闭服务器上的套接字。让我们看看将keepAlive设置为true会发生什么。
服务器
enter image description here
客户
enter image description here
这次大约只使用了一个 socket 。客户端和服务器之间存在持久连接,该连接超出了单个请求。
我了解到的一件事,多亏了great article,在Firefox上,您一次最多可以有6个并发持久连接。而且,您可以通过将maxSockets设置为6来使用代理来重现此内容。出于测试目的,我将其设置为2。此外,我不会从服务器返回任何内容,因此连接将被挂起。
agent: new http.Agent({ 
        keepAlive: true,
        maxSockets: 2,
    }),
//res.send('response from the server');
服务器
enter image description here
客户
enter image description here
客户端继续发送请求,但服务器仅接收到两个请求。两分钟后,再看http_server_timeout

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


接受了两个新请求。实际上,客户端已将后续请求排队,一旦服务器释放了套接字,客户端便可以从队列中发送两个新请求。
因此,我希望这会有所帮助。

关于node.js - NodeJS new Agent()和HTTP Keep-Alive header 之间的区别..?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44649566/

相关文章:

c++ - 读取 Windows 套接字上的 SIO_KEEPALIVE_VALS 字段(用于保持空闲和间隔时间)

node.js - 如何将数据插入到相关的 Mongoose 模式中?

node.js - 从多个 Docker 容器访问同一个 mongoDB 实例

javascript - Connect-busboy : When piping file to write steam, 文件为空或不正确,具体取决于类型

javascript - 如何将ajax数据传递给react中的组件

linux - 在 HTTP 请求上使用 HTTP Keep-alive 的方法

javascript - 如何在 node js 中使用 puppeteer 滚动页面 5 分钟(如果之前完成则更短)?

javascript - 为什么我的 Axios 实例在捕获的错误中不返回响应?

javascript - Axios 仅在自调用函数中调用一次 (Internet Explorer)

multithreading - Tomcat 多个请求相同的用户,相同的 url(是缓存吗?线程保持事件状态?)