3

现在我有如下的监听器代码。但是,我的服务器一直告诉我

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
    at EventEmitter.addListener (events.js:160:15)
    at Hub.<anonymous> (/home/ec2-user/AjaxIM-retail/server/middleware/im/hub.js:88:33)
    at /home/ec2-user/AjaxIM-retail/server/libs/utils.js:43:23
    at IncomingMessage.<anonymous> (/home/ec2-user/AjaxIM-retail/server/libs/authentication/lp/index.js:75:33)
    at IncomingMessage.EventEmitter.emit (events.js:117:20)
    at _stream_readable.js:920:16
    at process._tickCallback (node.js:415:13)
(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.

我读了一些帖子,有些人建议我“不要添加太多听众”……对吗?我应该怎么办?

   this.events.addListener('update', o_.bind(function(package) {
    if(this.clear != 0){
    delete this.sessions[this.clear];
    }
        var _package = package.toJSON();
        if(package.type == 'status' && package.status == 'offline') {
            var sids = Object.keys(this.sessions), sid, sess;
            for(sid in this.sessions) {
                sess = this.sessions[sid];
                if(sess.data('username') == package.username) {
                    if(sess.listeners.length)
                        sess.send(200, {type: 'goodbye'});
                    delete this.sessions[sid];
                    break;
                }
            }
        }
    }, this));
};

Hub.prototype.destroy = function(sid, fn) {
    this.set(sid, null, fn);
};

Hub.prototype.reap = function(ms) {
    var threshold = +new Date - ms,
        sids = Object.keys(this.sessions);
    for(var i = 0, len = sids.length; i < len; ++i) {
        var sid = sids[i], sess = this.sessions[sid];
        if(sess.lastAccess < threshold) {
         this.events.emit('update', new packages.Offline(sess.data('username')));
        }
    }
};


Hub.prototype.get = function(req, fn) {
    if(this.sessions[req.sessionID]) {
        fn(null, this.sessions[req.sessionID]);
    } else {
        this.auth.authenticate(req, o_.bind(function(data) {
            if(data) {
                var session = new User(req.sessionID, data);
                this.set(req.sessionID, session);
                this.auth.friends(req, data, o_.bind(function(friends) {
                    var friends_copy = friends.slice();
                    o_.values(this.sessions).filter(function(friend) {
                        return ~friends.indexOf(friend.data('username'));
                    }).forEach(function(friend) {
                        var username = friend.data('username');
                        friends_copy[friends_copy.indexOf(username)] =
                                            [username, friend.status()];
                    }, this);

                    session._friends(friends_copy);
                    session.events.addListener('status',
                        o_.bind(function(value, message) {
                            this.events.emit(
                                'update',
                                new packages.Status(session.data('username'),
                                                    value,
                                                    message)
                            );
                        }, this));
                    this.events.addListener('update',
                                      o_.bind(session.receivedUpdate, session));
                    this.set(req.sessionID, session);
                    fn(null, session);
                }, this));
            } else {
                fn();
            }
        }, this));
    }
};

老实说,我认为这很好。有什么问题吗?请指教。因为我的 node.js 服务器现在每 10-20 小时崩溃一次,并且不断向我抛出此侦听器警告和套接字挂起错误,如下所示:

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: socket hang up
    at SecurePair.error (tls.js:999:23)
    at EncryptedStream.CryptoStream._done (tls.js:695:22)
    at CleartextStream.read [as _read] (tls.js:496:24)
    at CleartextStream.Readable.read (_stream_readable.js:320:10)
    at EncryptedStream.onCryptoStreamFinish (tls.js:301:47)
    at EncryptedStream.g (events.js:175:14)
    at EncryptedStream.EventEmitter.emit (events.js:117:20)
    at finishMaybe (_stream_writable.js:354:12)
    at endWritable (_stream_writable.js:361:3)
    at EncryptedStream.Writable.end (_stream_writable.js:339:5)
    at EncryptedStream.CryptoStream.end (tls.js:633:31)
4

1 回答 1

3

这是来自 node.js 标准库的代码,它会触发此警告:https ://github.com/joyent/node/blob/master/lib/events.js#L160-L176 。因此,它基本上只是检查您的 EventEmitter 是否附加了 10 个以上(默认情况下)侦听器。您可以通过调用 setMaxListeners 来更改此值(传递 0 表示没有限制)。

所以警告本身与崩溃无关。但这确实可能是由泄漏引起的,即当您创建一个临时对象,然后附加一个侦听器函数,该函数在闭包中捕获该对象,然后不删除侦听器,这会导致对象永远留在内存中。也许这就是你的情况。如果不是,只需将限制设置为适当的值,如果是 - 好吧,这意味着整个最大侦听器确实有助于发现泄漏。

于 2013-10-04T20:41:24.137 回答