2013-10-23 116 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

非常好的答案,非常感謝,特別是對於發射器被破壞的部分。 :-) –

相關問題