【发布时间】:2020-08-07 20:58:26
【问题描述】:
我正在尝试在具有 25K+ 并发连接的视频游戏用户之间建立实时(私人)聊天。我们目前运行 32 个节点,用户可以通过负载均衡器进行连接。我要解决的问题是如何将消息路由给每个用户?
目前,我们正在使用 socket.io 和 socket.io-redis,其中每个 websocket 使用其用户 ID 加入一个房间,并且我们将他们应该收到的每条消息发送到该房间。这种设计的问题是我们达到了 Redis Pubsub 的极限,而 Socket.io 不能很好地扩展(socket.io 向所有节点发出消息,检查用户是否已连接,这是不可行的)。
我们当前的堆栈由 Postgres、Redis 和 RabbitMQ 组成。我一直在思考这个问题,并提出了 3 种不同的解决方案:
- 使用 RabbitMQ 路由所有消息。当用户连接时,我们创建一个带有用户 ID 和每个 websocket 连接队列的 fanout 类型的交换(我们必须为每个用户处理多个连接)。当我们想向该用户发出时,我们只需发布到该交易所。这种方法的问题是我们必须创建很多队列,而且我听说这可能不是很有效。
- 为 RabbitMQ 中的每个节点创建一个队列。当用户连接时,我们将节点和套接字 ID 保存在 Redis 集中,这样当我们必须向该特定用户发送消息时,我们首先获取节点列表,发送到每个节点队列,然后处理路由到应用程序中的特定客户端。这种方法的问题在于,在节点故障的情况下,我们可能会存储用户已连接,而事实并非如此。为了解决这个问题,我们需要使用户的 Redis 条目过期,但这不是一个完美的解决方案。另外,如果我们以后要实现群聊,那就意味着我们必须在 Rabbit 中发送重复的消息,这并不理想。
- 全面使用 Firebase 云消息传递。我们有一个移动应用程序,我们计划在用户未连接时将其用于推送通知,但即使用户已连接,它是否也适合?
您认为最适合我们的用例的是什么?你还有什么想法吗?
【问题讨论】:
标签: node.js sockets redis rabbitmq