节点JS - http.request()与连接池的问题(Node js - http.requ

2019-07-22 04:42发布

考虑下面简单的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();

这使得2000的HTTP请求到google.com,一前一后。 的问题是它会请求5号并暂停约3分钟,然后继续处理请求6 - 10,然后暂停另一3分钟,然后请求11 - 15,暂停等等。 编辑: 我试图改变www.google.com到本地主机,一个非常基本的Node.js应用程序运行在我的机器,它返回的“Hello world”,我仍然得到3分钟暂停。

现在我看我可以增加连接池的限制:

http.globalAgent.maxSockets = 20;

现在,如果我运行它,它处理请求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。


编辑:我发现,如果我上面的代码转换成一个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);
}

我不知道如果重仓的Node.js应用程序都不能达到许多并发连接。

Answer 1:

你必须消耗的响应。

请记住,在v0.10,我们降落streams2。 这意味着, data ,直到你开始寻找他们的事件不会发生。 所以,你可以做的东西是这样的:

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');
      });
    }
  });
});

然而,流的另一面,当你不读它不丢失数据,是他们实际上如果你不读它不会丢失数据! 也就是说,他们开始了暂停,并且一定要仔细阅读他们得到什么。

那么,什么是发生在你的测试是,你正在做一堆的请求,而不是消费的响应 ,并最终因为什么都没发生插座被由谷歌杀害,并假定你已经死了。

有些情况下,这是不可能的消费收到的消息:那就是,如果你不添加response在请求事件处理程序,或者你完全写,并完成response的服务器上而没有读请求消息。 在这种情况下,我们只是在倾倒垃圾为你的数据。

但是,如果您正在收听的'response'事件,这是你的责任来处理的对象。 添加response.resume()在你的第一个例子,你会看到它通过在一个合理的速度处理上。



文章来源: Node js - http.request() problems with connection pooling