NodeJS:如何调试"检测到EventEmitter内存泄漏.11个监听器添加"

Ifn*_*not 54 memory-leaks node.js eventemitter

如何调试抛出此错误的应用程序:

(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)
Run Code Online (Sandbox Code Playgroud)

我无法找到假定的泄漏对象来增加侦听器限制 .setMaxListeners(0);

解决方案(来自fardjad和jan salawa)

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

通过该解决方案,我可以得到这个新的痕迹:

(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)
Run Code Online (Sandbox Code Playgroud)

Ifn*_*not 32

事实证明这是nodejs核心中的一个错误,我们在这里讨论这个问题:https://github.com/joyent/node/issues/5108

针对错误的http服务器的解决方案,它会抛出EventEmitter memory leak detected并填满可用内存/可用CPU时间:

恢复旧版本v0.8.23.(您可以从这里下载并安装/编译它:http://blog.nodejs.org/2013/04/08/node-v0-8-23-legacy/)

更新2018年:我看到了关于这个主题的几个反馈,而这个问题似乎已经消失了多年.请注意,此响应仅适用于使用nodejs泄漏的http服务器构建.如果您在其他情况下,请查看其他人对此主题的回复并且不要降级您的版本(如此回复中所建议的那样),您将浪费您的时间.

  • 为什么在v0.10.24中仍然存在bug时它会关闭!? (22认同)
  • 甚至在6.2.2中 (5认同)
  • 我在v0.10.32看到这个 (3认同)
  • 也出现在v0.10.33中 (2认同)

jan*_*awa 12

对我来说,看起来你的事件循环被阻止了.如果您在node.js事件循环中执行cpu密集型任务,则会发生这种情况.您可以使用子进程执行密集型任务.

您可以使用以下方法检查阻塞node.js的内容:

  1. 测量每个呼叫的计算时间.记录如果时间很长,那么你知道app是行为不端的.
  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);
    Run Code Online (Sandbox Code Playgroud)
  3. 使用个人资料
  4. 使用日志记录和分析.它是Nodejitsu中使用的库.


小智 10

这正是发生在我身上的事.对我来说,我意外地在另一个事件监听器中嵌套了一个事件监听器.

查看您的代码并确保您没有事件侦听器块,例如另一个事件侦听器块(除非您是故意这样做):

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

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

   });
Run Code Online (Sandbox Code Playgroud)

在上面的错误示例中,socket.on('close')侦听器应该是socket.on('data')块的OUTSIDE.

在我收到5个数据流的情况下,socket.on('close')监听器正在等待关闭事件发生.当我关闭一次时,将执行另一个第四次结束事件.这显然不是我想要的.这是由于Node.js的性质是非阻塞的.由于回调功能,它"记住"事件.


nic*_*ojs 9

从节点 6 开始,您应该使用node --trace-warningshttps : //nodejs.org/api/cli.html#cli_trace_warnings

  • 或者,还有 https://github.com/niftylettuce/max-listeners-exceeded-warning (2认同)

far*_*jad 6

我试图将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);
}
Run Code Online (Sandbox Code Playgroud)


Vis*_*a k 5

如果您注册同一对象的特定事件超过11次,则会抛出此警告.

检查您是否正在呼叫您经常呼叫的功能中的特殊事件,这会导致多次注册事件.

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

  • 它应该是"超过10次". (4认同)