在Node.js中使用stream时内存泄漏?

假设我有一个简单的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样本,没有什么特别的 – 除了我订阅data和可读reqstream的end事件。 现在我想知道当我不再需要这些事件时,是否必须取消订阅这些事件?

或者当可读stream结束时它们被自动清除?

可能这样的代码导致内存泄漏?

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

在回答你的问题之前,让我们先讨论一下事件。 当你这样做:

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

listener被添加到emitter附加列表 。 稍后,当emitter触发事件时,它会通过遍历列表来通知订阅该事件的所有侦听器。 node.js事件发射器的神奇之处在于你不要自己声明或pipe理这个列表。

但是,无论何时调用.on() ,都会创build一个back-reference emitter – > listener。 这个引用将阻止GC收集这个监听器,如果你从不退订,就会产生一个“泄漏”。

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

当node.js认为你可能忘记注销监听者时,它将打印臭名昭着的“可能的泄漏检测”消息。

回到你的例子:

这不会造成泄漏,因为套接字(req + res)将首先被销毁。 由于它是发射器,node.js将强制删除所有侦听器 。