2013-10-23 115 views
6

假设我有一个简单的HTTP服务器,如:在Node.js中使用流时会发生内存泄漏?

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和可读req流的end事件。现在我想知道当我不再需要这些事件时是否必须取消订阅这些事件?

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

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

+3

[This](http://stackoverflow.com/questions/5326300/garbage-collection-with-node-js)可能会有所帮助。 – hexacyanide

+0

这实际上有助于更常见的意义。谢谢:-) –

回答

15

(这个答案包含指向node.js的源代码revelant部分)

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

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

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

但是,无论何时调用.on(),都会创建一个back-reference emitter - > listener。此参考将防止GC收集听众,如果您从未取消订阅,则会创建“泄漏”。

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

当node.js认为你可能忘记取消注册监听者时,它将打印臭名昭着的"possible leak detected"消息。

回到你的例子:

这不会产生泄漏,因为插座(REQ + RES)将首先被摧毁。由于它是发射器,node.js将forcibly remove all listeners

+0

非常好的答案,非常感谢,特别是对于发射器被破坏的部分。 :-) –

相关问题