使用jsdom将JSON反序列化为DOM时的Node.js内存泄漏

时间:2019-01-07 16:41:12

标签: node.js jsdom

我们使用jsdom将描述文档的自定义json转换为jsdom文档,因此我们可以使用CSS选择器轻松地修改文档。

问题是我们的服务器泄漏了内存并定期运行到OOME中。分析导致我们发现jsdom是罪魁祸首。

我们目前正在怀疑我们是否以错误的方式使用jsdom。如果无法解决此问题,我们将尝试使用cheerio而不是jsdom,这会由于重构和测试而导致工作量很大。

我拍摄的堆快照显示GC没有收集任何JSDOM对象。这意味着两次运行后,快照中将有两个JSDOM对象,而运行10次后,将有10个对象。

我尝试公开GC以强制垃圾收集。这没有帮助。

我已尝试在反序列化之后使用window.close(),但这也无济于事。

我们目前大致以以下方式使用jsdom:

let document = new JSDOM('<!DOCTYPE html>').window.document;
// json is the json to be deserialized
deserializeJsonNode(json);

function deserializeJsonNode(node_data, parent_node) {
  if (node_data === null) {
    return null;
  }
  let node;
  switch (node_data.nT) {
    case Node.COMMENT_NODE:
      node = document.createComment(node_data.attribute);
      break;
    case Node.TEXT_NODE:
      node = document.createTextNode(node_data.attribute);
      break;
    case Node.DOCUMENT_TYPE_NODE:
      node = document.implementation.createDocumentType(node_data.attribute);
      break;
    case Node.ELEMENT_NODE:
      node = document.createElement(node_data.attribute);
      break;
    case Node.DOCUMENT_NODE:
      node = document;
      break;
  }

  if (parent_node) {
    parent_node.appendChild(node);
  }

  var child_nodes = node_data.attribute;
  if (child_nodes) {
    child_nodes.forEach(child_node_data => {
      deserializeJsonNode(child_node_data, node);
    });
  }
  return node;
}

我希望有人对我们以错误的方式使用jsdom或我们可以尝试进一步调查我们的问题有任何想法。

谢谢。

1 个答案:

答案 0 :(得分:-1)

经过进一步分析,我们发现问题出在我们程序的早期。我们使用Cassandra with version 3.1的Node.js驱动程序,然后通过回调将检索到的数据传递给JSDOM。

似乎是由此导致的错误。升级到Cassandra驱动程序的3.2版并同步检索数据后,错误消失了。