当前位置: 首页 > 面试题库 >

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

长孙弘盛
2023-03-14
问题内容

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

它向google.com发出2000个HTTP请求,一个接一个。问题在于它会请求5号并暂停大约3分钟,然后继续处理请求6-10,然后再暂停3分钟,然后再请求11-15,然后暂停,依此类推。
编辑: 我尝试将www.google.com更改为localhost,这是运行我的计算机的极其基本的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应用程序是否可以同时达到这么多同时连接。


问题答案:

您必须消耗响应。

记住,在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');
      });
    }
  });
});

但是,不读取数据时不会丢失数据的流的另一面是,如果您不读取数据,它们 实际上
不会丢失数据!也就是说,它们开始处于暂停状态,您必须阅读它们才能取出所有内容。

因此,测试中发生的事情是,您发出了一堆请求并且 没有使用响应 ,然后套接字最终被Google杀死,因为什么也没发生,并假设您已经死亡。

在某些情况下, 不可能
使用传入的消息:也就是说,如果您没有response在请求上添加事件处理程序,或者完全response在服务器上编写并完成了消息而从未读取请求。在这种情况下,我们只是为您转储垃圾中的数据。

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



 类似资料:
  • 当我用我的节点运行MongoDB连接时。js应用程序哪个游戏平台我在这里面临着越来越多的MongoDB连接的问题[不使用任何查询,但它不断增加],达到819,我的MongoDB复制服务器停止响应,间接应用程序停止工作。但是我想保持至少20个关于如何解决这些问题的联系,请帮助我。 ** Mongodb连接:const connectionString=mongodb://AAAA:PASSWORD@

  • 问题内容: 如果我在闲置了一段时间后启动应用程序,那么我曾经遇到以下错误。(我正在使用Spring + Hibernate + MySQL作为DB) 我通过将以下内容添加到我的servlet-context.xml中解决了这个问题。 我在这里问了这个问题,这个问题是解决方案所特有的。我需要知道为什么会遇到这个错误。 我尝试了上面链接中提供的第一个选项(使用autoReconnect = true配

  • 我一直在想,节点中是否有。js mysql在一个池中使用多个连接(如果我在事务中有多个查询),还是在提交之前只使用一个连接?

  • 我向websphere V7添加了一个新的数据源。0,它工作正常,但在一段不活动时间后,池将返回死连接,java将进入等待状态,直到连接超时过期。如果我转到datasource管理页面并“测试连接”,连接池将再次工作。 我注意到,我们的oracle db会不时地关闭连接。 您知道如何从java重新激活连接吗?是否有其他方法来对抗Websphere池中的死连接?

  • 我正在使用node。js npm模块mysql用于连接mysql数据库。 我看到有可能使用: 两个泳池都有。getConnection(),连接。query()和连接。释放() 关于第二种情况,我有两个问题。 1)是否有任何自动重新连接的情况下,错误,失去连接,而使用pool.query?(处理断开功能,而使用池? 2) 使用第一种方法,我可以设置连接。on('error',function(){

  • C:\Users\ramachandran.s oracledb@1.2.0安装C:\Users\ramachandran.s\node\u modules\oracledb node gyp rebuild C:\Users\ramachandran.s\node\u modules\oracledb 我错过了什么,请帮忙