Запрос больших объектов JSON приводит к утечке памяти

У меня есть простое приложение NodeJs, которое действует как клиент REST и запрашивает большой объект JSON. Проблема в том, что он всегда заканчивается памяти (принимая более 6 ГБ). Я использую ручную сборку мусора (приложение началось с —expose_gc), но это, кажется, не очень помогает.

Вот мой код:

var needle = require('needle');
function getAllData() {
    getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
    getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
    getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
    getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
    getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");

    setInterval(function () {
        getAllData();
    }, 10 * 1000);
}

function getDataFromUrl(url) {
    needle.get(url, function (error, response) {
        if (!error && response.statusCode == 200) {
            console.log("do something");
        }
    });
}

function scheduleGc() {
    global.gc();
    setTimeout(function () {
        scheduleGc();
    }, 100 * 1000);
}

getAllData();
scheduleGc();

Я пытался запросить библиотеку, но у меня были те же результаты. Что я делаю не так?

P. s. Моя версия nodejs 6.9.1, игла версия 1.3.0

3 ответа

  1. Используйте инспектор узлов для поиска утечки. Это может быть внутренняя утечка nodejs или утечка из иглы и запроса. Я бы предпочел использовать родной http.requestязык, чтобы убедиться, что это не проблема библиотеки. Также вы можете разделить код на независимые части и запустить их отдельно, чтобы найти источник утечки.

    Существует еще один ответ, как обнаружить утечки памяти.

  2. Я нашел ошибку. Я использовал setInterval вместо setTimeout….

    var needle = require('needle');
    function getAllData() {
        getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
        getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
        getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
        getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
        getDataFromUrl("http://puppygifs.tumblr.com/api/read/json");
    }
    
    function getDataFromUrl(url) {
        needle.get(url, function (error, response) {
            if (!error && response.statusCode == 200) {
                console.log("do something");
            }
        });
    }
    
    function scheduleGc() {
        global.gc();
    
        setTimeout(function () {
            scheduleGc();
        }, 100 * 1000);
    }
    
    setInterval(function () {
        getAllData();
    }, 10 * 1000);
    
    scheduleGc();
    
  3. Это потому, что вы работаете с слишком большим количеством информации, 6 ГБ должны обрабатываться потоками .
    Это очень легко с иглой, просто избежать обратного вызова.
    Вот пример:

    'use strict';
     const needle = require('needle');
     const fs = require('fs');
     const out = fs.createWriteStream('bigFile.json');
     needle.get('http://puppygifs.tumblr.com/api/read/json').pipe(out);