Node.js进程内存溢出错误

8

致命错误:CALL_AND_RETRY_2 分配失败 - 进程内存不足

我看到这个错误,但不确定它来自哪里。我正在处理的项目具有以下基本工作流程:

  1. 从另一个来源接收XML post
  2. 使用xml2js解析XML
  3. 从新创建的JSON对象中提取所需信息并创建一个新对象。
  4. 将该对象发送给已连接的客户端(使用socket.io)

正在使用的Node模块包括:

  • xml2js
  • socket.io
  • choreographer
  • mysql

当我收到XML数据包时,我首先将其写入log.txt文件,以便稍后需要检查。我首先使用fs.readFile获取当前内容,然后写入新内容+旧内容。上次崩溃时,log.txt文件大约为2400KB,但在重新启动服务器后,它正常工作,因此我不认为这是问题所在。

我没有看到崩溃发生前的数据包,因此不确定导致崩溃的原因...没有新客户端连接,没有消息被发送...没有任何数据被解析。

编辑

由于Node一直在运行,所以我是否应该在每个对象完成其任务后使用delete <object>,例如我用来比较过去发生的事情的var now = new Date()。或者是步骤3中的结果对象,在将其传递给回调函数之后?

编辑2

我正在保留一个主对象,以防新客户端连接,他们需要查看过去的消息,但对象会被删除,它们不会在服务器的整个生命周期内保留,只会在客户端完成之前。目前,我正在执行类似于以下操作:

function parsingFunction(callback) {
    //Construct Object
    callback(theConstructedObject);
}

parsingFunction(function (data) {
   masterObject[someIdentifier] = data;
});

编辑 3

作为故障排除的另一步骤,我在解析器开始时候的 parser.on('end', function() {..}); 处转储了 process.memoryUsage().heapUsed 并解析了多个 XML 数据包。在整个测试过程中,最高的堆使用量约为 10-12 MB,尽管在正常情况下程序的使用量大约为 4-5 MB。我认为这不是一个特别严重的问题,但可能有助于找到问题所在。


1
new Date() 在这里肯定不是问题,长时间存活的对象将是问题所在。我怀疑 XML 解析器会泄漏,进程的内存使用情况如何?此外,使用 gdb 可以帮助找出 Node.js 或 V8 本身是否在此崩溃。如果不知道您正在解析的代码或 XML,很难给出任何进一步的建议。您应该尝试限制问题的范围,例如省略发送到 Socket.IO、日志记录等。您还可以访问我们的聊天室 http://chat.stackoverflow.com/rooms/338/node-js - Ivo Wetzel
目前我正在每一分钟转储当前的内存使用情况,在最后一个转储之前不应该发生任何事件,从控制台看起来崩溃了,但它的 RSS 是 152829952,vsize 是 24207360,heapTotal 是 5822464,heapUsed 是 4961744。 - A Wizard Did It
你试过使用 gdb 吗?没有代码我无法为你做任何事情 :/ - Ivo Wetzel
你在哪个平台上运行这个程序?我以前(现在仍然)在Cygwin上遇到过问题。 - dhruvbird
我曾经遇到过这样的问题,当我在循环中调用一个函数时。它应该跳出循环,但实际上没有,导致程序从那里泄漏出去了。我建议在函数开始处使用console.log来查看触发了多少次,以便更好地排查问题。 - Marshall
1个回答

2
也许你在无意间递归地关闭对象。一个疯狂的例子:
function f() {
  var shouldBeDeleted = function(x) { return x }

  return function g() { return shouldBeDeleted(shouldBeDeleted) }
}

要查找发生了什么,请启动node-inspector,并在疑似内存不足错误之前设置断点。然后点击“Closure”(在右边附近的作用域变量下方)。也许如果你点击一些东西,就会有所领悟,知道发生了什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接