【问题标题】:Node js socket explanationNode js socket解释
【发布时间】:2016-04-20 13:02:37
【问题描述】:

我正在构建一个应用程序,它将对远程 api 服务器进行大约一百万次调用。我可以将连接数量限制为例如 10 个吗?我是否将最大套接字设置为 10 可以吗?

我试图了解这些参数的作用:

keepAlive: false,
maxSockets: 999,
maxFreeSockets: 1

在节点http get函数中,代码如下:

var inputData = [];

for(i=1; i<=5000;i++){
    inputData.push('number' + i);
}

var options = {
    host: "localhost",
    port: 80,
    path: "/text.txt",
    keepAlive: false,
    maxSockets: 999,
    maxFreeSockets: 1
}


var limit = inputData.length;
var counter = 0;

function fetchData(number){

    return new Promise(function(resolve, reject){
        var http = require('http');

        fetch  = function(resp){
            var body = '';
            resp.on('data',function(chunk){
                body += chunk;
            })
            resp.on('end',function(){
                console.log(resp)
                resolve()
            })
            resp.on('error',function(err){
                console.log('error');
            })
        }
        var req = http.request(options, fetch);

        req.end();

    })
}



Promise.all(inputData.map(number => fetchData(number))).then(function(results) {
    console.log('finished');
    connection.end();

})
.catch(function(error) {
    console.log('there wa an error');
    console.log(error);
});

【问题讨论】:

  • 你试过阅读documentation吗?
  • OFC。我想知道这在现实生活中意味着什么。文档的解释并没有告诉我太多..
  • 文档实际上非常明确。 “agent.maxSockets:默认设置为 Infinity。确定代理可以为每个源打开多少个并发套接字。源是 'host:port' 或 'host:port:localAddress' 组合。”。有什么不清楚的地方?您是否有一个特定的场景,事情没有按照记录的那样工作?
  • 我需要进行大约 100 万次 API 调用,并且我需要将连接数量限制为 100 个并发连接,而​​不是对 api 服务器进行 DDOS。设置这个选项可以吗?当他们说代理时,他们是指申请吗? maxsockets 与 maxFreeSockets 有何不同,如何将它们放在一起以实现上述目标?我也应该改变保持平坦吗?上面的实现会完成这项工作吗?
  • 再一次,这一切都在文档中明确说明。请注意,根据该文档,它们是Agent 的选项,而不是http.clientRequest。如果您不信任文档(或您的实现),请从有限数量的请求和非常小的限制值开始,并使用 netstat 监控发生的情况,然后慢慢增加值。

标签: javascript node.js asynchronous


【解决方案1】:

您真的不想触发 1,000,000 个请求,并希望 maxSockets 一次将其管理为 100 个。有很多原因表明这不是做事的好方法。相反,您应该使用自己的代码将实时连接数管理​​为一次 100 个。

有很多方法可以做到这一点:

  1. 编写您自己的代码,启动 100 次,然后每次完成时,它会启动下一个。

  2. 使用 Bluebird 的 Promise.map(),它具有内置的并发功能,可以管理同时飞行的数量。

  3. 使用 Async 的 async.mapLimit(),它具有内置的并发功能,可以管理同时运行的数量。

至于自己编写代码来做到这一点,你可以这样做;

function fetchAll() {
    var start = 1;
    var end = 1000000;
    var concurrentMax = 100;
    var concurrentCnt = 0;
    var cntr = start;
    return new Promise(function(resolve, reject) {

        // start up requests until the max concurrent requests are going
        function run() {
            while (cntr < end && concurrentCnt < concurrentMax) {
                ++concurrentCnt;
                fetchData(cntr++).then(function() {
                    --concurrentCnt;
                    run();
                }, function(err) {
                    --concurrentCnt;
                    // decide what to do with error here
                    // to continue processing more requests, call run() here
                    // to stop processing more requests, call reject(err) here
                });
            }
            if (cntr >= end && concurrentCnt === 0) {
                // all requests are done here
                resolve();
            }        
        }

        run();
    });

}

【讨论】:

    【解决方案2】:

    我决定使用异步库。

    这是我的完整解决方案:

    var async = require('async')
    
    var http = require('http');
    
    var inputData = [];
    
    for(i=1; i<=2000;i++){
        inputData.push('number' + i);
    }
    
    var options = {
        host: "o2.pl",
        path: "/static/desktop.css?v=0.0.417",
        port: 80
    }
    
    function fetchData(number, callback){
    
        return new Promise(function(resolve, reject){
    
            fetch  = function(resp){
                var body = '';
                resp.on('data',function(chunk){
                    body += chunk;
                })
                process.stdout.write('.')
    
                callback()
    
                resp.on('error',function(err){
                    console.log('error');
                    console.log(err);
    
                })
            }
            var req = http.request(options, fetch);
    
            req.end();
    
        })
    }
    
    function foo(item, callback){
    
        return callback(false, 'foo');
    }
    
    async.mapLimit(inputData,100,fetchData,function(err, result){
        console.log('finished');
    })
    

    感谢您的帮助。

    【讨论】:

      猜你喜欢
      • 2014-10-18
      • 2017-08-07
      • 2015-12-24
      • 1970-01-01
      • 2013-04-20
      • 1970-01-01
      • 2022-12-27
      • 2015-06-14
      • 1970-01-01
      相关资源
      最近更新 更多