【问题标题】:Socket.io disconnect events and garbage collection for related closureSocket.io 断开事件和相关闭包的垃圾收集
【发布时间】:2015-10-19 18:20:08
【问题描述】:

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

我遇到的一个问题是,如果套接字连接断开,如果在断开连接的套接字上调用 emit,同一个套接字连接是否会尝试发送消息?换句话说,当您在断开连接的套接字上调用 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));

            });
        });
    }

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

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

  1. 允许进行垃圾收集以便服务器内存 足迹不会无限增长

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

这准确吗?

【问题讨论】:

    标签: node.js sockets websocket socket.io closures


    【解决方案1】:

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

    没有。在断开连接的套接字上对.emit() 的任何调用都将被忽略。 Here's the relevant source code snippet.

    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
    

    您不应该存储它们。把它留给关闭。那么以后就不需要将它们设置为null了。

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

    是的,当套接字断开连接时,垃圾收集将被释放。 socket.io 将从其内部队列中删除它们,不再有任何引用它们,它们将有资格进行垃圾收集。但是,您上面的代码与您发送事件的方式不正确。详情见下文。

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

    不要这样做。问题是您永远不会调用removeListener,因此在每个“更新”事件中,您将为自进程启动以来曾经连接过的每个套接字执行这些回调之一,甚至是断开连接的套接字。那是你的泄漏。相反,对于这种模式,只需在闭包之外设置一次广播:

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

    (除此之外:JSON.stringify 几乎肯定是不必要的。只有当你真的知道你必须在另一边将它作为字符串获取时才这样做。只发出一个对象可能是正确的)

    现在对于需要发送到特定套接字而不是所有连接的套接字的情况,您应该使用命名函数,以便您可以将每个 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);
      });
    });
    

    【讨论】:

    • 一旦我以某种方式确认信息,将选择作为答案:)
    猜你喜欢
    • 1970-01-01
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多