【问题标题】:Memory leak when using streams in Node.js?在 Node.js 中使用流时内存泄漏?
【发布时间】:2013-11-02 05:32:06
【问题描述】:

假设我有一个简单的 http 服务器,例如:

var http = require('http');

http.createServer(function (req, res) {
  req.on('data', function (data) {
    console.log('Got some data: ' + data);
  });

  req.on('end', function () {
    console.log('Request ended!');
  });

  res.end('Hello world!');
}).listen(3000);

所以,基本上是默认的 101 样本,到目前为止没有什么特别的——除了我订阅了可读的req 流的dataend 事件。现在我想知道当我不再需要这些事件时是否必须取消订阅它们?

或者当可读流结束时它们会自动清除?

这样的代码会导致内存泄漏吗?

【问题讨论】:

  • This 可能会有所帮助。
  • 这在更普遍的意义上实际上是有帮助的。谢谢:-)

标签: node.js memory-leaks


【解决方案1】:

(此答案包含指向 node.js 源代码相关部分的链接)

在回答您的问题之前,让我们先谈谈事件。当你这样做时:

emitter.on('an-event', listener);

listener 被添加到附加到 emitterlist 中。稍后,当emitter 触发事件时,它会通过遍历列表的方式通知所有订阅该事件的监听器。 node.js 事件发射器的神奇之处在于您无需自己声明或管理该列表。

但是,无论何时调用 .on(),都会创建一个 back-reference 发射器 -> 侦听器。如果您从未取消订阅,此引用将阻止 GC 收集侦听器并创建“泄漏”。

这在 node.js 中不会经常发生,因为通常,发射器在侦听器之前被销毁,但发生这种情况的实际情况是当您有一个长时间运行的连接(想想 Twitter 流 API)时,有时会重新连接。如果您不取消注册事件,您可能会从旧连接中获取事件并认为它们适用于新连接。这可能会让您认为新连接已关闭。

当 node.js 认为您可能忘记注销监听器时,它会打印臭名昭著的 "possible leak detected" 消息。

回到你的例子:

这不会造成泄漏,因为套接字 (req+res) 将首先被销毁。由于是发射器,node.js 将forcibly remove all listeners.

【讨论】:

  • 很好的答案,非常感谢,尤其是发射器被破坏的部分。 :-)
猜你喜欢
  • 2015-11-04
  • 2012-03-11
  • 2016-01-01
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多