在Node.js中使用流时发生内存泄漏? [英] Memory leak when using streams in Node.js?

查看:94
本文介绍了在Node.js中使用流时发生内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个简单的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事件.现在,我想知道当我不再需要这些事件时是否必须取消订阅这些事件?

还是在可读流结束时自动清除它们?

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

解决方案

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

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

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

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

但是,每当您调用.on()时,都会创建一个后向引用发射器->侦听器.此参考将防止GC收集侦听器,并且如果您永不退订,则会创建泄漏".

使用node.js很少会发生这种情况,因为通常,发射器会在侦听器之前被破坏,但是在现实世界中,发生这种情况的情况是当您具有长时间运行的连接(例如Twitter Streaming API)时,有时会重新连接.如果不注销事件,则可能会从旧连接中获取事件,并认为它们适用于新连接.这可能会使您认为新连接已关闭.

node.js将打印臭名昭著的检测到可能的泄漏" 提示您可能忘记注销监听器的消息.

回到您的示例:

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

Supposed I have a simple http server such as:

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);

So, basically the default 101 sample, nothing special so far - except that I subscribe to the data and the end event of the readable req stream. Now I wonder whether I have to unsubscribe those events when I no longer need them?

Or are they cleared automatically when the readable stream ends?

Could code like this cause a memory leak?

解决方案

(This answer contains links to the revelant parts of the node.js source code)

Before answering your question, let's talk about events. When you do this:

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

listener gets added to a list attached to emitter. Later, when emitter triggers the event, it notifies all the listeners subscribed to the event by iterating through the list. The magic of node.js event emitters is that you don't declare or manage that list yourself.

However, whenever you call .on(), you create a back-reference emitter -> listener. This reference will prevent the listener from being collected by the GC and create a "leak" if you never unsubscribe.

This does not happen very often with node.js, because usually, emitters are destroyed before listeners, but a real-world case where this happens is when you have a long running connection (think Twitter Streaming API) that sometimes reconnects. If you don't unregister events, you might get events from the old connection and think they apply to the new one. This can lead you to think the new connection has closed.

node.js will print the infamous "possible leak detected" message when it thinks you might be forgetting to unregister listeners.

Back to your example:

This won't create a leak because the socket (req+res) will be destroyed first. Since it's the emitter, node.js will forcibly remove all listeners.

这篇关于在Node.js中使用流时发生内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆