NodeJS: как отладить "обнаружена утечка памяти EventEmitter. 11 слушателей добавили"

как я могу отладить свое приложение, которое выдает эту ошибку:

(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 и Ян А. Салава)

с поисками Яна салавы я нашел рабочую библиотеку (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)

7 ответов


оказывается, что это ошибка в ядре nodejs, мы говорим об этой проблеме здесь:

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

решение для прослушиваемых http-серверов, которые бросают EventEmitter memory leak detected и заполнить доступную память / доступное время процессора :

вернуться к прежней версии v0.8.23.

Вы можете скачать и установить/скомпилировать его из здесь :

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


для меня похоже, что ваш цикл событий заблокирован. Это может произойти, если вы выполняете задачи с интенсивным процессором в узле.цикл событий 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.

Это именно то, что случилось со мной. Для меня я случайно вложил прослушиватель событий в другой прослушиватель событий.

посмотрите на свой код и убедитесь, что у вас нет блока прослушивателя событий в другом блоке прослушивателя событий, например(если вы не делаете это специально):

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

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

   });

в неправильном примере выше, сокет.on ('close') прослушиватель должен находиться вне сокета.on('data') блок.

в моем случае, когда я получил 5 потоков данных, розетка.прослушиватель on('close') ожидает события close. Когда я закрываю один раз, выполняется еще одно 4-е событие закрытия. Это явно не то, чего я хотел. Это связано с природой узла.js, который не блокируется. Он "запоминает" события из-за функции обратного вызова.


Я попытался создать прототип 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 раз.

проверьте, есть ли у вас вызов " on " для события particualr в функции, которую вы вызываете часто, это приводит к регистрации события несколько раз.

этой link помог мне понять это.


поскольку узел 6 Вы должны использовать node --trace-warnings: https://nodejs.org/api/cli.html#cli_trace_warnings


я столкнулся с той же проблемой при тестировании реагировать компоненты с помощью МОКа и фермент.

я смог решить свою проблему, явно размонтировав компоненты после того, как я закончил их тестирование.

проблема заключалась в том, что я монтировал компоненты несколько раз в своих тестах, которые затем добавляли больше слушателей, пока количество слушателей не достигло 11, и я получил предупреждение.

Я поменяла тестовый код, добавив вынесено.unmount () линии. Это исправило проблему для меня.

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

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