2013-10-04 108 views
2

現在我有聽衆代碼如下。然而,我的服務器不斷告訴我node.js服務器端的偵聽器過多?

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

回答

2

下面是node.js的非標準庫,這將觸發此警告的代碼: https://github.com/joyent/node/blob/master/lib/events.js#L160-L176。所以它基本上只是檢查你的EventEmitter是否有超過10個(默認)的監聽器。您可以通過調用setMaxListeners(傳遞0表示無限制)來更改此值。

所以這個警告本身與這次事故沒有關係。但它確實可能是由泄漏造成的,也就是當你創建一個臨時對象時,然後附加一個偵聽器函數,該函數捕獲閉包中的對象,然後不刪除偵聽器,這會導致對象永遠留在內存中。也許這是你的情況。如果不是,只要將限制設置爲適當的值(如果是),那麼這意味着整個最大聽衆的事情確實有助於發現泄漏。

+0

@vkurchaktin嗨,你能分享關於如何關閉一個監聽器的更多細節?每個人都告訴我這麼做,但我認爲我的代碼已經這樣做了......非常感謝您的幫助。 – jackhao

+1

完成後,您需要調用removeListener。要做到這一點,你需要引用監聽器函數本身,所以重要的是它不是匿名的。 – vkurchatkin