NodeJS Stream Drain Out of Memory问题

时间:2016-12-28 17:26:41

标签: node.js express stream out-of-memory

我在尝试从elasticsearch检索数据时遇到问题(OS Ubuntu,节点v4.2.6,res对象来自express作为可写流)。

我没有故意使用elasticsearch.js驱动程序。如果我使用ES驱动程序,结果保持不变。

这是我的代码:

   function getNextChunk() {
      console.log(process.memoryUsage());
      console.log("Getting chunks...");
      var options = { method : 'POST', url :  myHost + '/_search/scroll',
                      json : true,
                      body : { scroll: '60s', scroll_id: globalScope.scrollId }};
      request.post(options, function (err, resp, data) {
        if (err) return console.log(err);
        if (!data.hits.hits.length) { console.log("Done!"); return res.end(); }
        if (!res.write(JSON.stringify(data.hits.hits)))
          res.once('drain', function() { console.log("Draining..."); process.nextTick(getNextChunk); })
        else 
          process.nextTick(getNextChunk);
    });
}

这是输出:

{ rss: 165621760, heapTotal: 140918368, heapUsed: 116827240 }
Getting chunks...
Draining...
{ rss: 178941952, heapTotal: 153020000, heapUsed: 122942472 }
Getting chunks...
Draining...
{ rss: 191905792, heapTotal: 164065120, heapUsed: 140290016 }
Getting chunks...

(...)

Draining...
{ rss: 402944000, heapTotal: 358359648, heapUsed: 328087560 }
Getting chunks...
Draining...
{ rss: 414441472, heapTotal: 369453920, heapUsed: 345375496 }
Getting chunks...
Killed

正如您所看到的,heapUsed正在增加,直到进程被OS杀死。我想我错过了某个地方的东西,但我无法弄清楚。

顺便说一句,我试图用排水事件一个一个地写下每个命中,但仍然是相同的......

从此处编辑

我用这段代码做了一个新测试:

var data = {};

function safeWrite(err, resp, newData) {
  if (newData) data = newData;
  if (err) return console.log('Error !');
  if (!data.hits.hits.length) return console.log('Done !');
  while (data.hits.hits.length) {
    if (!res.write(JSON.stringify(data.hits.hits.pop()))) {
      res.once('drain', safeWrite);
      break;
    }
  }
  if (!data.hits.hits.length)
    process.nextTick(getNextChunk);
}

function getNextChunk() {
  console.log(process.memoryUsage());
  console.log("Getting chunks...");
  var options = { method : 'POST', url :  myHost + '/_search/scroll',
                  json : true,
                  body : { scroll: '1m', scroll_id: state.scrollId }};
  request.post(options, safeWrite);
}

getNextChunk();

有趣的是,如果我从另一个AWS服务器调用express,它会给出相同的结果。内存快速增加,并崩溃节点。如果我从缓慢的连接调用,垃圾收集器将内存恢复到其起始级别。垃圾收集器是否有可能没有时间完成其工作?我不这么认为,但是......

谢谢你的帮助!

0 个答案:

没有答案