Node.js 节点js-http.request()连接池问题

Node.js 节点js-http.request()连接池问题,node.js,request,connection-pooling,Node.js,Request,Connection Pooling,考虑以下简单的Node.js应用程序: var http = require('http'); http.createServer(function() { }).listen(8124); // Prevent process shutting down var requestNo = 1; var maxRequests = 2000; function requestTest() { http.request({ host: 'www.google.com', method:

考虑以下简单的Node.js应用程序:

var http = require('http');
http.createServer(function() { }).listen(8124); // Prevent process shutting down

var requestNo = 1;
var maxRequests = 2000;

function requestTest() {
    http.request({ host: 'www.google.com', method: 'GET' }, function(res) {
        console.log('Completed ' + (requestNo++));

        if (requestNo <= maxRequests) {
            requestTest();
        }
    }).end();
}

requestTest();
现在如果我运行它,它会处理请求1-20,然后暂停3分钟,然后请求21-40,然后暂停,依此类推

最后,经过一番研究,我了解到我可以通过在请求选项中设置
agent:false
来完全禁用连接池:

http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
    ...snip....
…它可以处理所有2000个请求

我的问题是,这样做是个好主意吗?是否有可能导致HTTP连接过多?为什么它会暂停3分钟呢?当然,如果我完成了连接,它应该直接将其添加回池中,以备下次请求使用,那么为什么它要等待3分钟呢?原谅我的无知

如果做不到这一点,Node.js应用程序在不锁定或崩溃的情况下发出大量HTTP请求的最佳策略是什么

我正在Mac OSX 10.8.2上运行Node.js版本0.10


Edit:我发现,如果我将上述代码转换为for循环,同时尝试建立一组连接,那么在大约242个连接之后,我就会开始出错。错误是:

Error was thrown: connect EMFILE
(libuv) Failed to create kqueue (24)
…和代码

for (var i = 1; i <= 2000; i++) {
    (function(requestNo) {
        var request = http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
            console.log('Completed ' + requestNo);
        });

        request.on('error', function(e) {
            console.log(e.name + ' was thrown: ' + e.message);
        });

        request.end();
    })(i);
}

for(var i=1;i您必须使用响应

记住,在v0.10中,我们登陆了streams2。这意味着,
数据
事件在您开始查找它们之前不会发生。因此,您可以执行以下操作:

http.createServer(function(req, res) {
  // this does some I/O, async
  // in 0.8, you'd lose data chunks, or even the 'end' event!
  lookUpSessionInDb(req, function(er, session) {
    if (er) {
      res.statusCode = 500;
      res.end("oopsie");
    } else {
      // no data lost
      req.on('data', handleUpload);
      // end event didn't fire while we were looking it up
      req.on('end', function() {
        res.end('ok, got your stuff');
      });
    }
  });
});
然而,流的另一面是,当您不读取数据时,它们不会丢失数据,即如果您不读取数据,它们实际上不会丢失数据!也就是说,它们开始暂停,您必须读取它们才能获得任何信息

所以,在你的测试中发生的是,你发出了一堆请求,而没有使用响应,然后最终套接字被google杀死,因为什么都没有发生,它假设你已经死了

在某些情况下,无法使用传入消息:即,如果不在请求上添加
响应
事件处理程序,或者在服务器上完全编写并完成
响应
消息,而不读取请求。在这些情况下,我们只是将数据转储到垃圾中


但是,如果您正在收听
'response'
事件,则处理对象是您的责任
在您的第一个示例中,您将看到它以合理的速度进行处理。

您的文件描述符已经用完,OSX上的文件描述符默认限制在相当低的256个。您可以使用
ulimit-n 2048
增加该数字,这将允许后续节点进程从同一个shell运行,以打开那些2000 connec我不知道这3分钟是从哪里来的,听起来像是连接池中的节流装置(或者谷歌正在节流你?)。感谢OSX文件描述符上的信息,这更有意义。我想在Linux上运行的实时网站上不会有问题。但至于3分钟等待,如果我在我的机器上点击一个本地运行的Node.js web应用程序,我就知道了。通过阅读,我想知道3分钟的超时是否是Google服务器的保持活动超时(虽然如果我正确理解了文档,只要你继续请求,就不应该等到保留有效期到期后再开始新的请求…)robertklep-参见上面的编辑,但我尝试将www.google.com更改为localhost,这是一个运行我的机器的极其基本的Node.js应用程序,返回“Hello world”,我仍然有3分钟的暂停时间。我猜3分钟来自内存分配weet,谢谢!是的,“response.resume()”有效。正如您所说,使用带有“response.on('data',function(){})”的响应也有效。另外,只需调用“this.destroy()”在回调中似乎也起到了作用。我还要补充一点,文档中并没有明确说明这一点——但如果这是streams2和0.10刚刚发布的新行为,可能可以理解。在这个代码解决方案中http.request发生在哪里?换言之,完整的代码是什么样子的?
http.createServer(function(req, res) {
  // this does some I/O, async
  // in 0.8, you'd lose data chunks, or even the 'end' event!
  lookUpSessionInDb(req, function(er, session) {
    if (er) {
      res.statusCode = 500;
      res.end("oopsie");
    } else {
      // no data lost
      req.on('data', handleUpload);
      // end event didn't fire while we were looking it up
      req.on('end', function() {
        res.end('ok, got your stuff');
      });
    }
  });
});