检测到套接字 io 可能的 EventEmitter 内存泄漏

Posted

技术标签:

【中文标题】检测到套接字 io 可能的 EventEmitter 内存泄漏【英文标题】:socket io Possible EventEmitter memory leak detected 【发布时间】:2019-04-18 08:36:06 【问题描述】:

一旦事件完成,我想删除监听器以避免套接字 io 中的这个问题。

我收到了这个错误

MaxListenersExceededWarning:检测到可能的 EventEmitter 内存泄漏。添加了 11 个连接侦听器。使用emitter.setMaxListeners() 增加限制

我尝试过使用 removeAllListeners / removeListener / off 但它们都不起作用。

const io = socket(httpServer); 

(async () => 
  await io.on('connection', async function (client) 

       // Some Code //

        await client.emit('message', "Done")
        io.removeAllListeners("connection")
    )
)

【问题讨论】:

【参考方案1】:

如果您想要与单个客户端的单套接字连接,请使用 await io.once 而不是 await io.on。否则,它会为服务器端的每个请求生成多个服务器侦听器实例。

【讨论】:

它不起作用,因为这个异步 IIFE 函数位于另一个函数中,每次客户端发生某些事情时都会触发该函数。 那么你必须重构你的代码逻辑。您必须在启动时在 app.js 中调用 io.once,然后通过 req.io 监听事件。您必须将套接字附加到您的应用程序,但您会在每次请求时调用它。检查与 websockets 相关的这个答案。一般是同一个问题。 ***.com/questions/22429744/…【参考方案2】:

我遇到了同样的问题,我可以使用以下代码解决问题,

mqttClient.off('message', mqttClient.listeners("message")[0]) 
它将从事件中删除所需的侦听器。

mqttClient.listeners("message"):我将返回附加到“消息”事件的侦听器数组。

您也可以使用removeListner() 这里我使用了 MQTT 案例。 socket io 也可以按照此流程处理。

【讨论】:

【参考方案3】:

您可以使用--trace-warnings 跟踪该警告(应该在nodenodemonbabel-node 中工作)。

在我的例子中,在 Node 中使用 mysql 我遇到了这个错误:

(node:44) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit

at _addListener (events.js:247:17)

at PoolConnection.addListener (events.js:263:10)

at /app/server.js:100:1 // Redacted, but here's the specific line and column for the error 

at Ping.onOperationComplete (/app/node_modules/mysql/lib/Pool.js:110:5)

at Ping.<anonymous> (/app/node_modules/mysql/lib/Connection.js:526:10)

at Ping._callback (/app/node_modules/mysql/lib/Connection.js:488:16)

at Ping.Sequence.end (/app/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24)

at Ping.Sequence.OkPacket (/app/node_modules/mysql/lib/protocol/sequences/Sequence.js:92:8)

at Protocol._parsePacket (/app/node_modules/mysql/lib/protocol/Protocol.js:291:23)

at Parser._parsePacket (/app/node_modules/mysql/lib/protocol/Parser.js:433:10)

这就是问题所在:

const mysql_pool = mysql.createPool(mysql_pool_options);

// ...

io.on('connection',function(socket)
  socket.on('foobar', function(foo) 
    // Stuff going on ...

    // Get connection and query the database 
    mysql_pool.getConnection(function(err, current_mysql_connection) 
       current_mysql_connection.query(my_great_query, function(query_error, results) 
           // Some other stuff I do ...
       );

       // ?  Here's the issue, I didn't need to do this here ? 
       current_mysql_connection.on('error', function(err) 
           // console.log(err);
       );
    );
  );
);

【讨论】:

以上是关于检测到套接字 io 可能的 EventEmitter 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

为啥不尝试 I/O 就不可能检测到 TCP 套接字已被对等方优雅地关闭?

如何检测套接字连接何时丢失?

libevent 如何检测到套接字已关闭

TCP 套接字关闭但未被进程检测到

UDP套接字缓冲区溢出检测

循环依赖检测到猫鼬错误