NodeJS:如何debugging“检测到EventEmitter内存泄漏。 11位听众添加了“

我怎样才能debugging我的应用程序引发这个错误:

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit. Trace at Socket.EventEmitter.addListener (events.js:160:15) at Socket.Readable.on (_stream_readable.js:653:33) at Socket.EventEmitter.once (events.js:179:8) at TCP.onread (net.js:527:26) 

我无法find假设的泄漏对象,以增加侦听器限制,通过.setMaxListeners(0);

解决scheme(来自fardjad和jan salawa)

随着jan salawa的search,我发现了一个工作库( longjohn ),用于增加堆栈跟踪详细信息。 随着fardjad的回应,我发现我们必须原型EventEmitter.addListener EventEmitter.on

有了解决scheme,我可以得到这个新的痕迹:

 (node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit. Trace at EventEmitter.addListener.EventEmitter.on (xxx/main.js:44:15) at Readable.on (_stream_readable.js:653:33) at ServerResponse.assignSocket (http.js:1072:10) at parser.onIncoming (http.js:1979:11) at parserOnHeadersComplete (http.js:119:23) at socket.ondata (http.js:1912:22) at TCP.onread (net.js:510:27) 

事实certificate,这是nodejs核心中的一个bug,我们在这里讨论这个问题:

https://github.com/joyent/node/issues/5108

针对窃听的HTTP服务器的解决scheme, EventEmitter memory leak detected并填充可用内存/可用CPU时间:

恢复到旧版本v0.8.23

你可以从这里下载并安装/编译它:

http://blog.nodejs.org/2013/04/08/node-v0-8-23-legacy/

对我来说,看起来你的事件循环被阻塞了。 如果您在node.js事件循环中执行cpu密集型任务,则可能发生这种情况。 你可以使用subprocess来完成密集的任务。

您可以使用以下方法检查是什么阻止node.js:

  1. 测量每个通话的计算时间 。 logging时间是否高,所以你知道应用程序是行为不当。
  2. 设置一个日志时间表,让你知道什么时候阻塞循环
     function timeTick() { var startTime = (new Date().getTime()); function onTick() { var interval = (new Date().getTime()) - startTime; if(interval > 5) console.log('timeTick(): WARNING: interval = ' + interval); } process.nextTick(onTick); } setInterval(timeTick, 1000); 
  3. 使用configuration文件
  4. 用它来logging和分析。 这是在Nodejitsu中使用的库。

这正是我发生的事情。 对我而言,我意外地在另一个事件监听器中嵌套了一个事件监听器。

看看你的代码,确保你没有在另一个事件监听器块中的事件监听器块(例如,除非你故意这样做):

 socket.on('data', function(data) { //code goes here socket.on('close' , function() { //code goes here }); }); 

在上面的错误示例中,socket.on('close')侦听器应该位于socket.on('data')块的外部。

在我的情况下,当我收到5个数据stream时,socket.on('close')监听器正在等待closures事件发生。 当我closures一次,另一个第四次closures事件将执行。 这显然不是我想要的。 这是由于非阻塞的Node.js的性质。 它会记住由于callback函数而导致的事件。

我试图将EventEmitter原型添加到addListener中,但是我无法工作

挂钩addListener你可以做这样的事情:

 // on the first line of your main script var events = require("events"), EventEmitter = events.EventEmitter; var originalAddListener = EventEmitter.prototype.addListener; EventEmitter.prototype.addListener = function (type, listener) { if (this.listenerCount(this, type) >= 10) { // TODO: PLACE YOUR CODE FOR DEBUGGING HERE } originalAddListener.apply(this, arguments); } 

如果您注册了同一对象的特定事件超过11次,则会引发此警告。

检查您是否正在经常打电话的function中“打”呼叫事件,导致多次注册事件。

这个链接帮助我理解了这一点。

当使用摩卡testingReact组件时,我遇到了同样的问题。

在完成testing后,我可以通过明确卸载组件来解决问题。

问题是,我在testing中多次挂载组件,然后添加更多的监听器,直到监听器的数量达到11,并且我收到警告。

我通过添加rendered.unmount()行来更改我的testing代码。 这为我解决了这个问题。

 describe('<CircleArc />', () => { it('renders', function () { const rendered = mount(<CircleArc />); assert.ok(rendered.find('path')); rendered.unmount(); }); }