node.js 检测到可能的 EventEmitter 内存泄漏

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9768444/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:21:56  来源:igfitidea点击:

possible EventEmitter memory leak detected

node.jsmemory-leakseventemitter

提问by Riz

I am getting following warning:

我收到以下警告:

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

I wrote code like this in server.js:

我在 server.js 中写了这样的代码:

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

How to fix this ?

如何解决这个问题?

采纳答案by Corey Richardson

This is explained in the node eventEmitter documentation

这在节点 eventEmitter 文档中进行解释

What version of Node is this? What other code do you have? That isn't normal behavior.

这是什么版本的node?你还有什么代码?这不是正常行为。

In short, its: process.setMaxListeners(0);

简而言之,它的: process.setMaxListeners(0);

Also see: node.js - request - How to “emitter.setMaxListeners()”?

另请参阅:node.js - request - How to “emitter.setMaxListeners()”?

回答by voltrevo

I'd like to point out here that that warning is there for a reason and there's a good chance the right fix is notincreasing the limit but figuring out why you're adding so many listeners to the same event. Only increase the limit if you know why so many listeners are being added and are confident it's what you really want.

我想在这里指出,该警告的存在是有原因的,并且很有可能正确的解决方法不是增加限制,而是弄清楚为什么要向同一事件添加如此多的侦听器。仅当您知道为什么要添加如此多的听众并确信这是您真正想要的时才增加限制。

I found this page because I got this warning and in my case there was a bug in some code I was using that was turning the global object into an EventEmitter! I'd certainly advise against increasing the limit globally because you don't want these things to go unnoticed.

我找到这个页面是因为我收到了这个警告,在我的例子中,我使用的一些代码中有一个错误,它将全局对象变成了一个 EventEmitter!我当然建议不要在全球范围内增加限制,因为您不希望这些事情被忽视。

回答by zag2art

By default, a maximum of 10 listeners can be registered for any single event.

默认情况下,最多可以为任何单个事件注册 10 个侦听器。

If it's your code, you can specify maxListeners via:

如果是您的代码,您可以通过以下方式指定 maxListeners:

const emitter = new EventEmitter()
emitter.setMaxListeners(100)
// or 0 to turn off the limit
emitter.setMaxListeners(0)

But if it's not your code you can use the trick to increase the default limit globally:

但如果不是你的代码,你可以使用这个技巧来全局增加默认限制:

require('events').EventEmitter.prototype._maxListeners = 100;

Of course you can turn off the limits but be careful:

当然,您可以关闭限制,但要小心:

// turn off limits by default (BE CAREFUL)
require('events').EventEmitter.prototype._maxListeners = 0;

BTW. The code should be at the very beginning of the app.

顺便提一句。代码应该在应用程序的最开始。

ADD: Since node 0.11 this code also works to change the default limit:

添加:从节点 0.11 开始,此代码也可用于更改默认限制:

require('events').EventEmitter.defaultMaxListeners = 0

回答by Rayee Roded

The accepted answer provides the semantics on how to increase the limit, but as @voltrevo pointed out that warning is there for a reason and your code probably has a bug.

接受的答案提供了有关如何增加限制的语义,但正如@voltrevo 指出的那样,警告是有原因的,您的代码可能有错误。

Consider the following buggy code:

考虑以下错误代码:

//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');
}

Now observe the correct way of adding the listener:

现在观察添加监听器的正确方法:

//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');
}

Search for similar issues in your code before changing the maxListeners (which is explained in other answers)

在更改 maxListeners 之前搜索代码中的类似问题(在其他答案中进行了解释)

回答by Davis Dulin

Replace .on()with once(). Using once()removes event listeners when the event is handled by the same function.

替换.on()once()once()当事件由同一函数处理时,使用将删除事件侦听器。

If this doesn't fix it, then reinstall restler with this in your package.json "restler": "git://github.com/danwrong/restler.git#9d455ff14c57ddbe263dbbcd0289d76413bfe07d"

如果这不能解决它,那么在你的 package.json “restler”中重新安装restler:“git://github.com/danwrong/restler.git#9d455ff14c57ddbe263dbbcd0289d76413bfe07d”

This has to do with restler 0.10 misbehaving with node. you can see the issue closed on git here: https://github.com/danwrong/restler/issues/112However, npm has yet to update this, so that is why you have to refer to the git head.

这与 restler 0.10 对 node 的行为不端有关。您可以在此处查看 git 上已关闭的问题:https: //github.com/danwrong/restler/issues/112但是,npm 尚未对此进行更新,因此您必须参考 git head。

回答by Legolas Bloom

I am getting this warning too when install aglio on my mac osx.

在我的 mac osx 上安装 aglio 时,我也收到此警告。

I use cmd fix it.

我用cmd修复它。

sudo npm install -g npm@next

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

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

回答by Sandeep PC

Node Version : v11.10.1

节点版本:v11.10.1

Warning message from stack trace :

来自堆栈跟踪的警告消息:

process.on('warning', e => console.warn(e.stack));
(node:17905) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit
    at _addListener (events.js:255:17)
    at Connection.addListener (events.js:271:10)
    at Connection.Readable.on (_stream_readable.js:826:35)
    at Connection.once (events.js:300:8)
    at Connection._send (/var/www/html/fleet-node-api/node_modules/http2/lib/protocol/connection.js:355:10)
    at processImmediate (timers.js:637:19)
    at process.topLevelDomainCallback (domain.js:126:23)

After searching for github issues, documentation and creating similar event emitter memory leaks, this issue was observed due to node-apnmodule used for iOS push notification.

在搜索 github 问题、文档并创建类似的事件发射器内存泄漏后,由于用于 iOS 推送通知的node-apn模块而观察到此问题。

This resolved it :

这解决了它:

You should only create one Provider per-process for each certificate/key pair you have. You do not need to create a new Provider for each notification. If you are only sending notifications to one app then there is no need for more than one Provider.

If you are constantly creating Provider instances in your app, make sure to call Provider.shutdown() when you are done with each provider to release its resources and memory.

您应该为您拥有的每个证书/密钥对为每个进程创建一个提供程序。您不需要为每个通知创建一个新的 Provider。如果您只向一个应用程序发送通知,则不需要多个提供程序。

如果您不断在应用中创建 Provider 实例,请确保在完成每个 Provider 后调用 Provider.shutdown() 以释放其资源和内存。

I was creating provider object each time the notification was sent and expected the gc to clear it.

每次发送通知时我都在创建提供者对象,并希望 gc 清除它。

回答by lwdthe1

I prefer to hunt down and fix problems instead of suppressing logs whenever possible. After a couple days of observing this issue in my app, I realized I was setting listeners on the req.socketin an Express middleware to catch socket io errors that kept popping up. At some point, I learned that that was not necessary, but I kept the listeners around anyway. I just removed them and the error you are experiencing went away. I verified it was the cause by running requests to my server with and without the following middleware:

我更喜欢寻找并解决问题,而不是尽可能地抑制日志。在我的应用程序中观察这个问题几天后,我意识到我正在req.socketExpress 中间件中设置侦听器以捕获不断弹出的套接字 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();
    }

Removing that middleware stopped the warning you are seeing. I would look around your code and try to find anywhere you may be setting up listeners that you don't need.

删除该中间件停止了您看到的警告。我会环顾您的代码并尝试找到您可能设置不需要的侦听器的任何地方。

回答by Vikas Gautam

In my case, it was child.stderr.pipe(process.stderr)which was being called when I was initiating 10 (or so) instances of the child. So anything, that leads to attach an event handler to the same EventEmitter Object in a LOOP, causes nodejs to throw this error.

就我而言,它是child.stderr.pipe(process.stderr)在我启动 10 个(左右)子实例时被调用的。因此,任何导致在 LOOP 中将事件处理程序附加到同一个 EventEmitter 对象的事情都会导致 nodejs 抛出此错误。

回答by Motate

Sometimes these warnings occur when it isn't something we've done, but something we've forgotten to do!

有时,当这些警告不是我们做过的事情,而是我们忘记做的事情时,就会发生这些警告!

I encountered this warning when I installed the dotenv package with npm, but was interrupted before I got around to adding the require('dotenv').load() statement at the beginning of my app. When I returned to the project, I started getting the "Possible EventEmitter memory leak detected" warnings.

我在使用 npm 安装 dotenv 包时遇到了这个警告,但在我开始在我的应用程序开头添加 require('dotenv').load() 语句之前被中断了。当我返回项目时,我开始收到“检测到可能的 EventEmitter 内存泄漏”警告。

I assumed the problem was from something I had done, not something I had not done!

我认为问题出在我做过的事情上,而不是我没有做的事情上!

Once I discovered my oversight and added the require statement, the memory leak warning cleared.

一旦我发现了我的疏忽并添加了 require 语句,内存泄漏警告就清除了。