【问题标题】:Best Performance - emit to sockets via a loop or rooms最佳性能 - 通过循环或房间发射到套接字
【发布时间】:2017-12-04 08:50:12
【问题描述】:

我们目前有一个聊天应用程序,当向适当的用户(可能是 1 个或多个,取决于对话中的用户数)发送消息时,我们会循环通过与服务器的所有套接字 (Socket.io 2.0.2) 连接( NodeJS)根据成员 ID 值获取用户拥有的套接字列表,因为每个用户都可以从多个设备连接。代码如下所示,以确定我们应该发送消息的用户拥有哪些套接字,

    var sockets = Object.keys(socketList);
    var results = [];
    for (var key in sockets) {
        if (hasOwnProperty(socketList[sockets[key]].handshake.query, 'token')) {
            if (JSON.parse(socketList[sockets[key]].handshake.query.member).id === memberId) {
                results.push(socketList[sockets[key]]);
            }
        }
    }

必须循环通过套接字连接似乎效率低下,我想知道有没有更好的方法。我的想法是为每个用户创建一个房间,大多数用户将只有一个连接,但有些用户将通过多个设备连接,因此他们的房间中可以有多个插座。然后我只会广播到适当的房间,而不是总是循环通过所有套接字。鉴于 95% 的用户将只有一个套接字连接,我不确定这种方法是否更有效,并且希望对此有所帮助。 谢谢。

【问题讨论】:

    标签: socket.io


    【解决方案1】:

    首先,socket.io 已经为每个用户创建了一个房间。该房间的名称为socket.id。房间是非常轻的物体。它们基本上只是由一个对象组成,其中包含房间中所有套接字的 id。所以,应该毫不犹豫地使用房间。如果它们适合您正在做的模型,请使用它们。

    至于循环自己和发射到房间,真的没有区别 - 使用使您的代码更简单的那个。当你发射到一个房间时,它所做的只是循环通过房间中的套接字并单独发送到每个套接字。

    必须循环通过套接字连接似乎效率低下,我想知道有没有更好的方法。

    房间的主要优点是它们是套接字的预构建关联,因此您不必动态确定要发送到哪些套接字 - 在正确的房间中已经有一个套接字列表可以发送到。因此,仅发送到房间中的所有套接字可能比执行代码正在执行的操作更有效,因为您的代码动态地试图找出要发送到哪些套接字,而不是发送到已经制作的列表。这会有所作为吗?这取决于整个套接字列表的长度以及计算要发送到哪些套接字的成本。我的猜测是,这两种方式可能都不会产生太大影响。

    向房间发送消息在实际发送部分效率并不高。每个套接字都必须单独发送消息,因此某人(您的代码或 socket.io 房间代码)将以任何一种方式循环通过套接字列表。底层操作系统不包含将单个消息发送到多个套接字的功能。每个套接字都必须单独发送。

    然后我将只向适当的房间广播,而不是总是循环通过所有套接字。

    发送到房间对您来说是一种编程方便,但 socket.io 无论如何都会在幕后循环。

    【讨论】:

    • 是从这一点出发,如果您想从 server 发送到多个套接字,循环遍历套接字 id 字符串数组并发送同样合理使用socket.to('${socketId}').emit('hey', 'message to a socket's room'); 发送到他们各自的房间,因为它是循环相同的数组并使用io.to('${socketId}').emit('hey', 'message to a socket'); 发送到他们各自的sockets?我引用socket.io/docs/emit-cheatsheet,谢谢。
    • @user1063287 - 从网络的角度来看,您是否手动迭代并发送到每个或是否让 socket.io 为您完成都无关紧要。无论哪种方式,它都是相同数量的单独传输。因此,任何性能差异仅在于每段代码如何迭代列表,差异可能微不足道。仅供参考,您不需要socket.to('${socketId}').emit(...)。你可以做socket.to(socketId).emit(...)
    • 当你说let socket.io do it for you时,你仍然需要遍历一个socket id数组,不是吗?所以你可以发送到每个基于套接字 id 的房间? (在这种情况下,用户在他们连接时加入的基于默认套接字 id 的房间中)
    • @user1063287 - 让 socket.io 意味着通过io.emit() 向所有人广播或使用房间来管理用户集合并让 socket.io 使用io.to() 发送给他们。
    • @jfriend00 他的例子不会慢一点吗?在您链接到此处的源代码中:stackoverflow.com/questions/40093554/… 它只对消息进行一次编码,而他的语法将对其进行多次编码。只是想提一下。您确实提到了网络的观点,但在特定情况下,整体广播的效率会稍微高一些。
    【解决方案2】:

    我会使用Socket.io rooms 来完成你想做的事情。

    服务器端,将客户端添加到聊天室:

    socket.join('some room');
    

    然后我会使用socket.to('some room').emit 将发件人消息发送给房间中的所有参与者。

    【讨论】:

    • 感谢您的回复。对于 socket.io 为每个用户创建和维护房间的资源使用是否有任何问题?
    • 不是一个很大的数字,大约 10,000 个。
    猜你喜欢
    • 2018-03-03
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    相关资源
    最近更新 更多