【问题标题】:Difference between NodeJS new Agent() and HTTP Keep-Alive header..?NodeJS new Agent() 和 HTTP Keep-Alive 标头之间的区别..?
【发布时间】:2017-11-22 18:59:54
【问题描述】:

我正在使用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.
}

还有HTTP headertimeoutmax 选项。

这些选项似乎不一致(keepAliveMsecsmaxSocketsmaxFreeSockets vs timeoutmax),这表明它们是不同的。

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

【问题讨论】:

    标签: node.js axios keep-alive


    【解决方案1】:

    这是基于我自己收集到的。

    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 设置为 falsemaxSockets 设置为 Infinity

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

    agent 到底是什么?

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

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

    关于 timeoutma​​x,据我所知,这些是在为 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 设置为falsemaxSocketsInfinity

    但是,要使代理配置具有任何意义,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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-29
      • 2012-09-15
      • 2015-11-15
      • 1970-01-01
      • 1970-01-01
      • 2018-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多