1. ホーム
  2. javascript

[解決済み】MaxListenersExceededWarning: EventEmitterのメモリリークの可能性が検出されました。11メッセージのリステナーを追加しました。emitter.setMaxListeners()を使って上限を増やす。

2022-02-21 12:15:46

質問

重複した解決策になるかもしれませんが、スタックオーバーフローにある解決策が私にはうまくいきません。

問題点

(node:5716) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message lis
teners added. Use emitter.setMaxListeners() to increase limit.

私のコードベースは巨大で、時々このエラーに直面しますが、なぜ起こっているのかわかりません。リスナー数の制限を増やそうとしましたが、残念ながらうまくいきません。

const EventEmitter = require('events');
const emitter = new EventEmitter()
emitter.setMaxListeners(50)

アップデイト

いくつかのブラウジングの後、私は警告をトレースするために次のコマンドを実行します。

node --trace-warnings index.babel.js

私のsocket.ioのコードが問題であることが判明しました。私はRedisでsocket.ioを使用しています。これはエラーです

node:14212) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message li
steners added. Use emitter.setMaxListeners() to increase limit
    at _addListener (events.js:281:19)
    at RedisClient.addListener (events.js:298:10)
    at Namespace.<anonymous> (D:/newProject/services/socket.js:21:17)
    at emitOne (events.js:115:13)
    at Namespace.emit (events.js:210:7)
    at Namespace.emit (D:\newProject\node_modules\socket.io\lib\namespace.js:213:10)
    at D:\newProject\node_modules\socket.io\lib\namespace.js:181:14
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

これがそのコードです(ただし、このコードはより特殊なタスクのためのものであり、常に実行されるわけではありません)。

const redis = require('redis');
const config = require('../config');
const sub = redis.createClient(config.REDIS.port, config.REDIS.host);
const pub = redis.createClient(config.REDIS.port, config.REDIS.host);

sub.subscribe('spread');

module.exports = io => {
  io.on('connection', socket => {
    /* To find the User Login  */
    let passport = socket.handshake.session.passport; 

    if (typeof passport !== 'undefined') {
      socket.on('typing:send', data => {
        pub.publish('spread', JSON.stringify(data));
      });

      sub.on('message', (ch, msg) => {
        // This is the Exact line where I am getting this error
        io.emit(`${JSON.parse(msg).commonID}:receive`, { ...JSON.parse(msg) });
      });
    }
  });
};

解決方法は?

のデフォルトの制限は イベントエミッター は10です。emitter.setMaxListenersで増やすことができます。私の提案は、明示的に要求されない限り、また、あなたが登録を解除しなかったためにリスナーが増加するまでは、これを変更しないことです。さて、あなたのコードに。

const redis = require('redis');
const config = require('../config');
const sub = redis.createClient(config.REDIS.port, config.REDIS.host);
const pub = redis.createClient(config.REDIS.port, config.REDIS.host);

sub.subscribe('spread');

module.exports = (io) => {
  io.on('connection', (socket) => {
    // this callback will be executed for all the socket connections.
    let passport =
      socket.handshake.session.passport; /* To find the User Login  */

    if (typeof passport !== 'undefined') {
      socket.on('typing:send', (data) => {
        pub.publish('spread', JSON.stringify(data));
      });

      // this is where you are subscribing for each and every socket connected to your server
      sub.on('message', (ch, msg) => {
        // this is the Exact line where I am getting this error

        // whereas you are emitting messages on socket manager, not on the socket.
        io.emit(`${JSON.parse(msg).commonID}:receive`, { ...JSON.parse(msg) });
      });
    }
  });
};

上記のコードを分析すると、もしサーバーに20のソケット接続を開くと、20回サブスクライブすることになりますが、これは間違っています。 もし、Redisで発行されたメッセージをサーバレベルで受信し、それをioに出力することが目的であれば、以下のようなコードになるはずです。

const redis = require('redis');
const config = require('../config');
const sub = redis.createClient(config.REDIS.port, config.REDIS.host);
const pub = redis.createClient(config.REDIS.port, config.REDIS.host);

sub.subscribe('spread');

module.exports = (io) => {
  sub.on('message', (ch, msg) => {
    // this is the Exact line where I am getting this error
    io.emit(`${JSON.parse(msg).commonID}:receive`, { ...JSON.parse(msg) });
  });

  io.on('connection', (socket) => {
    let passport =
      socket.handshake.session.passport; /* To find the User Login  */

    if (typeof passport !== 'undefined') {
      socket.on('typing:send', (data) => {
        pub.publish('spread', JSON.stringify(data));
      });
    }
  });
};