[Node.js] обнаружена утечка памяти EventEmitter


Answers

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

Я нашел эту страницу, потому что получил это предупреждение, и в моем случае была ошибка в некотором коде, который я использовал, который превращал глобальный объект в EventEmitter! Я бы посоветовал не увеличивать лимит во всем мире, потому что вы не хотите, чтобы эти вещи оставались незамеченными.

Question

Я получаю следующее предупреждение:

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace: 
    at EventEmitter.<anonymous> (events.js:139:15)
    at EventEmitter.<anonymous> (node.js:385:29)
    at Server.<anonymous> (server.js:20:17)
    at Server.emit (events.js:70:17)
    at HTTPParser.onIncoming (http.js:1514:12)
    at HTTPParser.onHeadersComplete (http.js:102:31)
    at Socket.ondata (http.js:1410:22)
    at TCP.onread (net.js:354:27)

Я написал код, подобный этому в server.js:

http.createServer(
    function (req, res) { ... }).listen(3013);

Как это исправить?




Я предпочитаю выслеживать и исправлять проблемы, а не сужать журналы, когда это возможно. После нескольких дней наблюдения за этой проблемой в моем приложении я понял, что настраивал слушателей на req.socket в промежуточном программном обеспечении Express, чтобы уловить ошибки сокета io, которые постоянно возникали. В какой-то момент я узнал, что это не обязательно, но я все равно слушал слушателей. Я просто удалил их, и ошибка, с которой вы столкнулись, ушла. Я подтвердил, что это было причиной, запустив запросы на мой сервер с и без следующего промежуточного программного обеспечения:

socketEventsHandler(req, res, next) {
        req.socket.on("error", function(err) {
            console.error('------REQ ERROR')
            console.error(err.stack)
        });
        res.socket.on("error", function(err) {
            console.error('------RES ERROR')
            console.error(err.stack)
        });
        next();
    }

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




У меня была такая же проблема. и проблема была вызвана тем, что я слушал порт 8080, на 2 слушателя.

setMaxListeners() работает нормально, но я бы не рекомендовал его.

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




Вы сказали, что используете process.on('uncaughtException', callback);
Где вы выполняете это заявление? Он находится в http.createServer переданном http.createServer ?
Если да, другая копия того же обратного вызова будет привязана к событию uncaughtException при каждом новом запросе, потому что function (req, res) { ... } будет выполняться каждый раз, когда приходит новый запрос, и так будет выполняться инструкция process.on('uncaughtException', callback);
Обратите внимание: объект процесса является глобальным для всех ваших запросов и добавляет слушателей к его событию каждый раз, когда приходит новый запрос, не имеет никакого смысла. Возможно, вы не захотите такого поведения.
Если вы хотите добавить нового слушателя для каждого нового запроса, вы должны удалить все предыдущие прослушиватели, прикрепленные к событию, поскольку они больше не потребуются, используя:
process.removeAllListeners('uncaughtException');




Принятый ответ дает семантику о том, как увеличить лимит, но поскольку @voltrevo указал, что предупреждение существует по какой-то причине, и ваш код, вероятно, имеет ошибку.

Рассмотрим следующий код ошибки:

//Assume Logger is a module that emits errors
var Logger = require('./Logger.js');

for (var i = 0; i < 11; i++) {
    //BUG: This will cause the warning
    //As the event listener is added in a loop
    Logger.on('error', function (err) {
        console.log('error writing log: ' + err)
    });

    Logger.writeLog('Hello');
}

Теперь обратите внимание на правильный способ добавления слушателя:

//Good: event listener is not in a loop
Logger.on('error', function (err) {
    console.log('error writing log: ' + err)
});

for (var i = 0; i < 11; i++) {
    Logger.writeLog('Hello');
}

Поиск похожих вопросов в коде перед изменением maxListeners (что объясняется в других ответах)




Я также получаю это предупреждение при установке aglio на моем mac osx.

Я использую cmd для исправления.

sudo npm install -g npm@next

https://github.com/npm/npm/issues/13806




Иногда эти предупреждения возникают, когда это не то, что мы сделали, а то, что мы забыли сделать!

Я столкнулся с этим предупреждением, когда установил пакет dotenv с номером npm, но был прерван, прежде чем я успел добавить инструкцию require ('dotenv'). Load () в начале моего приложения. Когда я вернулся к проекту, я начал получать предупреждения об обнаружении утечки «Возможная ошибка EventEmitter».

Я предположил, что проблема была в том, что я сделал, а не в том, чего я не сделал!

Как только я обнаружил свой надзор и добавил оператор require, предупреждение об утечке памяти очистилось.