56

如何调试引发此错误的应用程序:

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

我找不到假设的泄漏对象来增加监听器限制 .setMaxListeners(0);

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

通过 jan salawa 的搜索,我找到了一个工作库 ( longjohn ),用于增加堆栈跟踪的详细程度。根据 fardjad 的回复,我发现我们必须对EventEmitter.addListener AND 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)
4

8 回答 8

32

原来这是nodejs核心的一个bug,我们在这里讨论这个问题:https ://github.com/joyent/node/issues/5108

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

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

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

于 2013-04-25T18:28:30.257 回答
12

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

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

  1. 测量每个调用的计算时间。如果时间很长,请记录下来,以便您知道应用程序行为不端。
  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. 使用个人资料。
  4. 使用来记录和分析。它是Nodejitsu中使用的库。
于 2013-03-25T14:49:32.860 回答
11

这正是发生在我身上的事情。对我来说,我不小心将一个事件侦听器嵌套在另一个事件侦听器中。

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

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

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

   });

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

就我而言,当我收到 5 个数据流时,socket.on('close') 侦听器正在等待关闭事件发生。当我关闭一次时,将执行另一个第四次关闭事件。这显然不是我想要的。这是由于 Node.js 的非阻塞性质。由于回调函数,它会“记住”事件。

于 2014-03-22T01:30:56.000 回答
9

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

于 2018-03-31T18:15:13.180 回答
7

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

检查您是否在您经常调用的函数中对特定事件进行“on”调用,这会导致多次注册事件。

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

于 2015-10-21T08:49:58.357 回答
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);
}
于 2013-03-23T12:47:11.703 回答
0

我在运行单元测试时看到了这一点。我的单元测试反复调用正在调用的代码:

process.on("uncaughtException", () => { ... });

我不得不使用依赖注入来注入一个伪造的进程对象,从而解决了这个问题。

主.js:

export function main(myProcess) {
    myProcess.on("uncaughtException", () => { ... });
}

if (require.main === module) { // to prevent this from executing when running unit tests
    main(process);
}

我的单元测试会做:

const fakeProcess = jasmine.createSpy("process", ["on"]);
main(fakeProcess);
于 2019-07-22T14:46:47.967 回答
-1

我在使用mocha酵素测试React组件时遇到了同样的问题。

在完成测试后,我能够通过显式卸载组件来解决我的问题。

问题是我在测试中多次安装组件,然后添加了更多的侦听器,直到侦听器的数量达到 11,我收到了警告。

我通过添加render.unmount()行更改了我的测试代码。这解决了我的问题。

describe('<CircleArc />', () => {

    it('renders', function () {
        const rendered = mount(<CircleArc />);
        assert.ok(rendered.find('path'));
        rendered.unmount();
    });
}
于 2016-04-05T17:48:58.303 回答