首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >节点js -连接池的http.request()问题

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

Stack Overflow用户
提问于 2013-03-20 19:57:44
回答 1查看 10.4K关注 0票数 10

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

代码语言:javascript
复制
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();

它一个接一个地向google.com发出2000个HTTP请求。问题是它请求5号并暂停大约3分钟,然后继续处理请求6-10,然后再暂停3分钟,然后请求11-15,暂停等等。编辑:我试着将改为localhost,这是一个运行我的机器的极其基本的Node.js应用程序,返回"Hello“,我仍然有3分钟的停顿。

现在我读到我可以增加连接池限制:

代码语言:javascript
复制
http.globalAgent.maxSockets = 20;

现在,如果我运行它,它处理请求1-20,然后暂停3分钟,然后请求21-40,然后暂停,等等。

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

代码语言:javascript
复制
http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
    ...snip....

...and --它将运行所有2000年的请求--很好。

我的问题是,这样做好吗?是否存在可能导致HTTP连接过多的危险?为什么它要暂停3分钟,当然如果我已经完成了连接,它应该将它直接添加回池中,以便下一个请求使用,那么它为什么要等待3分钟呢?原谅我的无知。

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

我正在MacOSX10.8.2上运行Node.js版本0.10。

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

代码语言:javascript
复制
Error was thrown: connect EMFILE
(libuv) Failed to create kqueue (24)

...and密码..。

代码语言:javascript
复制
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应用程序是否能够达到这么多的同时连接。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-21 00:46:19

你必须消耗这个响应。

记住,在0.10版中,我们登陆了streams2。这意味着除非您开始寻找data事件,否则不会发生它们。所以,你可以这样做:

代码语言:javascript
复制
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事件处理程序,或者在服务器上不读取请求就完全写入和完成response消息。在这种情况下,我们只需将数据转储到垃圾中。

但是,如果您正在侦听'response'事件,那么处理对象是您的责任。在第一个示例中添加一个response.resume(),您将看到它以合理的速度处理。

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15533448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档