NodeJS new Agent()和HTTP Keep-Alive标头之间的区别..?

Ste*_*ast 6 keep-alive node.js axios

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

当在Node中使用时,axios提供了new http.Agent()请求配置中指定的选项。

HTTP代理选项有:

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.
}
Run Code Online (Sandbox Code Playgroud)

还有带有和选项的HTTP标头timeoutmax

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

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

jpe*_*erl 28

这是基于我自己收集的。

HTTP 标头Keep-Alive: timeout=5, max=1000只是随 HTTP 请求一起发送的标头。将其视为在两台主机(客户端和服务器)之间进行通信的一种方式。主持人说'嘿,请保持连接有效'。这对于现代浏览器来说是自动的,服务器可能会实现也可能不会实现。该keepAlive: true代理是作为文档说:

不要与 Connection 标头的 keep-alive 值混淆。

这意味着keepAlive: false!= Connection: close。它与标题没有任何关系。代理将处理 TCP 级别的事务,包括 HTTP 客户端上的套接字等。

keepAlive boolean 即使没有未完成的请求也保持套接字,因此它们可以用于未来的请求而无需重新建立 TCP 连接

只要您为 HTTP 客户端使用代理,Connection: Keep-Alive就会使用 。除非 keepAlive被设定为falsemaxSocketsInfinity

const options = {
  port: 3000,
  agent: new http.Agent({ 
        keepAlive: false ,
        maxSockets: Infinity,
    })
};//----> Connection: close
Run Code Online (Sandbox Code Playgroud)

代理究竟是什么?

代理负责管理 HTTP 客户端的连接持久性和重用。它维护一个给定主机和端口的待处理请求队列,为每个重用单个套接字连接,直到队列为空,此时套接字要么被销毁,要么放入一个池中,以便再次用于请求到相同的主机和端口。是销毁还是池化取决于keepAlive选项。

池连接为它们启用了 TCP Keep-Alive,但服务器可能仍会关闭空闲连接,在这种情况下,它们将从池中删除,并在为该主机和端口发出新的 HTTP 请求时建立新连接。服务器也可能拒绝允许通过同一个连接的多个请求,在这种情况下,必须为每个请求重新建立连接,并且不能合并。代理仍将向该服务器发出请求,但每个请求都将通过新连接发生。

关于timeoutmax,据我所知,这些是在为 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
Run Code Online (Sandbox Code Playgroud)

这使

Connection:Keep-Alive
Keep-Alive:timeout=5, max=100
Run Code Online (Sandbox Code Playgroud)

但是这些与 NodeJS 无关?我会让更多有经验的人回答这个问题。总之,代理将不设置这些,也不会改变Connection: Keep-Alive,除非设置keepAlivefalsemaxSocketsInfinity如上说。

但是,要使代理配置具有任何意义,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
Run Code Online (Sandbox Code Playgroud)

服务器是一个快速应用程序(我将跳过详细信息)

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);
        });
    });
Run Code Online (Sandbox Code Playgroud)

为了让您看到keepAlive: false!= Connection: close,让 keepAlive 设置为 false 并查看服务器端会发生什么。

agent: new http.Agent({ 
        keepAlive: false,
        maxSockets: 20
    })
Run Code Online (Sandbox Code Playgroud)

服务器

在此处输入图片说明

客户

在此处输入图片说明

如您所见,我没有将 maxSockets 设置为 Infinity,因此即使代理中的 keepAlive 设置为 false,Connection 标头也设置为 Keep-Alive。但是,每次向服务器发送请求时,服务器上的套接字都会在每次请求后立即关闭。让我们看看当我们将 keepAlive 设置为 true 时会发生什么。

服务器

在此处输入图片说明

客户

在此处输入图片说明

这一次,只使用了一个插座。客户端和服务器之间存在持久连接,该连接持续超过单个请求。

由于这篇很棒的文章,我了解到的一件事是,在 Firefox 上,您一次可以拥有多达 6 个并发持久连接。您可以通过将 maxSockets 设置为 6 来使用代理重现这一点。出于测试目的,我将其设置为 2。而且,我不会从服务器返回任何内容,因此连接将保持挂起。

agent: new http.Agent({ 
        keepAlive: true,
        maxSockets: 2,
    }),
Run Code Online (Sandbox Code Playgroud)
//res.send('response from the server');
Run Code Online (Sandbox Code Playgroud)

服务器

在此处输入图片说明

客户

在此处输入图片说明

客户端不断发送请求,但服务器只收到了两个请求。然而两分钟后,看到http_server_timeout

假定套接字超时之前不活动的毫秒数。

接受两个新请求。实际上,客户端已将后续请求排入队列,一旦服务器释放套接字,客户端就能够从队列中发送两个新请求。

所以,我希望这会有所帮助。