Adam
Adam

Reputation: 3518

Node js socket explanation

I am building an application that will be making about a million calls to a remote api server. Will I be able to limit amount of connections to for example 10? Do I set max sockets to 10 will do it?

I am trying to understand what do these parameters do:

keepAlive: false,
maxSockets: 999,
maxFreeSockets: 1

In node http get function, in the following code:

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

Upvotes: 3

Views: 3442

Answers (2)

Adam
Adam

Reputation: 3518

I decided to use the async library.

Here is my complete solution to this:

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

Thank you for your help.

Upvotes: 1

jfriend00
jfriend00

Reputation: 707876

You really don't want to fire off 1,000,000 requests and somehow hope that maxSockets manages it to 100 at a time. There are a whole bunch of reasons why that is not a great way to do things. Instead, you should use your own code that manages the number of live connections to 100 at a time.

There are a number of ways to do that:

  1. Write your own code that fires up 100 and then each time one finishes, it fires up the next one.

  2. Use Bluebird's Promise.map() which has a built-in concurrency feature that will manage how many are inflight at the same time.

  3. Use Async's async.mapLimit() which has a built-in concurrency feature that will manage how many are inflight at the same time.

As for writing code yourself to do this, you could do something like this;

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

}

Upvotes: 6

Related Questions