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   51   2013-03-23 04:35:14

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 в функции, которую вы часто вызываете, это приводит к регистрации для события несколько раз.

этой ссылка помогла мне понять это.

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

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

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

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

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

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

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