首页 > 解决方案 > Socket IO 和动态房间

问题描述

如果有人对 Websockets / Socket IO 有经验,希望你能指出我正确的方向。

我制作了一个 Discord Clone,我正在尝试对其进行优化以更好地扩展。现在,当用户发送消息时,我会在数据库中查询该服务器的所有用户部分,并向他们的特定套接字发出消息。这显然不能很好地扩展,因为每条消息都需要在客户端列表中进行昂贵的查询和查找

// Emit messages to only users part of specific server
    // Will only return list of users part of server and active in last 10 minutes
    sqlQuery = `SELECT userservers.user_id FROM userservers 
                  JOIN users ON users.user_id = userservers.user_id AND users.user_last_active > (NOW() - INTERVAL 10 minute)
                  WHERE server_id = ${sql.escape(serverId)}`;
    const users = await sql.query(sqlQuery);
    action = { type: "message", payload: msg };

    // Iterate over users, and find them in clients list
    // Emit over socket only to that user
    users.forEach((user) => {
      clients.forEach((client) => {
        if (client.userId === user.user_id) {
          io.to(client.id).emit(user.user_id, action);
        }
      })
    });

但是,为每个服务器使用房间将消除我查询数据库的需要。我知道我可以在套接字服务器首次启动时执行此操作

// Get server list from Mysql DB
servers.forEach((server) => {
    socket.join(server.name);
}

但是我的问题变成了,当用户在应用程序已经运行后创建新服务器时,它不会更新列表。

我可能错过了一些关于创建动态房间的概念。

编辑:我认为解决方案可能是每次创建“服务器”时,我都会向套接字服务器发送一条消息,以便它可以加入那个“房间”

标签: javascriptnode.jswebsocketsocket.io

解决方案


现在,当用户发送消息时,我会在数据库中查询该服务器的所有用户部分

我认为您可以向所有在线用户提交广播消息,因此forEach client => io.to(clientId) 您可以向所有连接的用户提交广播消息而不是io.emit('some event', { for: 'everyone' });

我也想知道你为什么要创建很多服务器?您可以通过 using 将服务器划分为命名空间const namespace = io.of('/thisIsASeparateNamespace');,还可以通过以下方式向该命名空间内的所有用户提交广播消息namespace.emit('some event', { for: 'everyone in name space' });

所以你的聊天结构可以是这样的

服务器

  • 命名空间//用于单独的聊天应用程序/或类似松弛的工作空间
  • 房间 // 用于群聊
  • ClientID // 一对一

推荐阅读