Socket.io断开相closures包的事件和垃圾回收

我有一个基本的实时服务器,使用socket.io。 我的问题涉及到闭包和垃圾收集,以及是否应该打扰在关联数组中存储套接字连接,或者只是将其closures以pipe理连接。

我有一个问题是,如果一个套接字连接断开,是否将相同的套接字连接尝试发送一个消息,如果在断开的套接字调用发射? 换句话说,当你在一个断开的套接字上调用socket.emit()会发生什么?

下面是一些代码,底部的问题:

var socketio = require('socket.io); var io = socketio.listen(server); var EE = require('events').EventEmitter; var ee = new EE(); //this is actually initialized elsewhere but now you know what it is var connectedUsers = {}; //associative array to store socket connections by socket.id io.on('connection', function (socket) { connectedUsers[socket.id] = socket; //should I bother storing the socket connections in the associative array or just leave it to the closure to store them socket.on('disconnect', function () { connectedUsers[socket.id] = null; //should I bother removing }); ee.on('update',function(data){ socket.emit('update',JSON.stringify(data)); }); ee.on('insert',function(data){ socket.emit('insert',JSON.stringify(data)); }); ee.on('delete',function(data){ socket.emit('delete',JSON.stringify(data)); }); }); } 

所以我的主要问题是,用于闭包的内存量将随着套接字连接的数量而线性增长,并且永远不会停止或减less。 socket.io断开事件通过垃圾回收释放内存?

看来我需要重新组织上面的代码来完成两件事情:

  1. 以允许垃圾收集,以便服务器内存占用不会无限增长

  2. 以避免发布每个套接字连接的所有数据,这就是现在正在做的事情。

这是准确的吗?

我有一个问题是,如果一个套接字连接断开连接,相同的套接字连接尝试发送一个消息,如果在断开的套接字调用发射? 换句话说,当你在一个断开的套接字上调用socket.emit()会发生什么?

.emit() 。在断开的套接字上对.emit()任何调用都将被忽略。 这是相关的源代码片段 。

 connectedUsers[socket.id] = socket; //should I bother storing the socket connections in the // associative array or just leave it to the closure to store them 

你不应该存储它们。 把它closures。 之后不需要将它们设置为null。

所以我的主要问题是,用于闭包的内存量将随着套接字连接的数量而线性增长,并且永远不会停止或减less。 socket.io断开事件通过垃圾回收释放内存?

是的,事情将被释放垃圾收集sockets断开连接。 socket.io会从内部队列中删除它们,没有任何东西可以引用它们,它们将有资格进行垃圾回收。 但是,上面的代码与发送事件的方式不正确。 详情请参阅下文。

 ee.on('update',function(data){ socket.emit('update',JSON.stringify(data)); }); 

不要这样做这种模式。 问题是你永远不会调用removeListener所以在每一个“更新”事件,你将执行这些callback之一,每个套接字曾经连接,因为进程开始,甚至是断开连接。 这是你的泄漏。 相反,对于这种模式,只需在closures之外设置一次广播即可:

 ee.on('update', function (data) { io.sockets.emit('update', data); }); 

(另外:JSON.stringify几乎肯定是不必要的,只有当你真的知道你必须把它作为一个string的时候才行,只是发出一个对象可能是正确的)

现在,对于需要发送到特定套接字而不是所有连接的套接字的情况,您应该使用命名函数,以便您可以将每个ee.on与相应的ee.removeListener以正确地防止幻像侦听器。

 io.on('connection', function(socket) { // every socket gets a closure // and a distinct onUpdate function object function onUpdate(data) { socket.emit('update', data); } ee.on('update', onUpdate); socket.on('disconnect', function() { // removes the handler for this specific socket, // leaving the others intact ee.removeListener('update', onUpdate); }); });