NodeJS Express Becomes Unresponsive and Getting Timeouts

871 views Asked by At

I have a feeling I have some kind of leak somewhere, but I'm not sure how to identify or troubleshoot. I'm using express and the request module for nodejs. Under load, https calls made by request to the Facebook Graph API start experiencing long delays or time out altogether. At first I thought it was a throttling issue on the receiving side (Facebook), but if I make a simple C# console application that calls the same URLs several hundred times, none of the response times are greater than 150ms. However, the same code in node varies from 50ms to up to 10s. If I set the timeout property when using request, I start getting ESOCKETTIMEDOUT errors. If I set pool.maxsize on the request options to 100, then I get ETIMEDOUT errors instead.

How can I figure out where my hang up is occurring?

Here's a sample of my use of the request module. I also tried adding this to my app:

require('http').globalAgent.maxSockets = Infinity;
require('https').globalAgent.maxSockets = Infinity;



var executeGetUrl = function getUrl(url, cacheKey, parseJson, accessToken, callback) {

    if (accessToken) {
        url = url + '?access_token=' + accessToken;
    }

    try {
        request({url: url, timeout: 10000, 'pool.maxSockets' : 100}, function (err, res, body) {
            if (err) {
                logger.error('Made facebook api call to ' + url + ' with error ' + err);
                callback(err, null);
                return;
            }

            if (parseJson) {
                try {
                    body = JSON.parse(body);
                } catch (err) {
                    callback(new Error('Could not parse ' + res.body + ': ' + err), null);
                    return;
                }

                if (body.error) {
                    err = new Error('Error calling ' + url + '. ' + body.error.message);
                    err.code = body.error.code;
                    callback(err, null);
                }
                else {
                    callback(null, body || {});
                }
            } else {
                if (res.statusCode != 200) {
                    callback(new Error(res.body));
                } else {
                    callback(null, res.body || {});
                }
            }
        });
    } catch (err) {
        callback(null, err);
    }
};

I'm memoizing the results for 60 seconds, but that doesn't seem to have any relation to the problem

var getUrl = memoize(executeGetUrl, {async: true, maxAge: 60000, length: 2});

And using the function in a promise chain

    var deferred = q.defer();

    getUrl(photosUrl, null, false, null, function (err, body) {

        if (err) {
            deferred.reject(err);
            return;
        }
        deferred.resolve(body);
    });

    return deferred.promise;
0

There are 0 answers