SocketIO扩展架构和大房间要求

时间:2014-05-14 12:10:51

标签: node.js redis rabbitmq scalability socket.io

我们在大型聊天应用程序中使用socketIO。

在某些时候我们想要发送"存在" (用户可用性)给所有其他用户。

io.in('room1').emit('availability:update', {userid='xxx', isAvailable: false});

room1可能包含很多用户(最多500个)。当触发许多可用性更新时,我们观察到NodeJS负载显着增加。

这个想法是使用类似于带有Socket IO的redis商店。让Web浏览器客户端连接到不同的NodeJS服务器。

当我们想要发射到一个房间时,我们发出"发射到房间1"使用Redis PubSub ZeroMQ甚至RabbitMQ进行持久性的所有其他NodeJS进程的有效负载。每个进程本身都会调用自己的io.in('room1').emit来定位其连接用户的子集。

这种设置的一个问题是进程间通信可能变得非常繁忙,我想知道它是否会成为未来的问题。

这是我想到的架构。

enter image description here

4 个答案:

答案 0 :(得分:2)

您正在寻找这个图书馆: https://github.com/automattic/socket.io-redis

可以与此发射器一起使用: https://github.com/Automattic/socket.io-emitter

答案 1 :(得分:1)

关于可用的用户功能,我认为有两种选择,你可以创建一个“队列用户”,其中将内容“公共数据”来自连接的用户,或者你可以使用交换机绑定信息来显示连接的用户。如果你使用“用户队列”,这对每个“房间”都是相同的,你可以在用户外出时更新它,从队列中“弹出”它的状态消息(尽管你必须“重新组织”所有队列消息对于它)。

尽管如此,我认为RabbitMQ是专为异步通信而设计的,并且它不是非常有用的近似具有来自用户的存在或不存在的寄存器。我认为对于那些您不知道用户何时会收到消息及其“真实可用性”(“火灾和遗忘架构”)的应用程序来说,它会更好。 ZeroMQ需要从零开始的更多工作,但您可以通过更好的性能实现更适合您情况的工作。

来自RabbitMQ网站的发布/订阅示例可能是开始像您一样的新设计的一个好点,其中一条消息同时发送给多个用户。总之,我将为用户创建两个队列(接收和发送队列消息),我将使用特定的交换为每个“房间聊天”控制用户在每个房间使用交换绑定的信息。您始终为用户提供两个队列,并创建交换以将其绑定到一个或多个“聊天室”。

我希望这个答案对你有用,抱歉我的英语不好。

答案 2 :(得分:1)

您可以批量更改并且每隔5秒钟只分发一次吗?换句话说,在每个节点服务器上,只需拍摄一个'快照'所有用户当前状态的每X秒(例如,已连接','空闲'等),然后将其发送到群集中的其他相关服务器。

然后每个服务器执行相同的操作,每隔5秒左右,它会将相同的消息 - 仅用户状态的更改 - 作为一个批处理对象数组发送到所有连接的客户端。

现在,我很惊讶您尝试将每个用户的信息作为数据包发送。批处理似乎可以很好地解决您的问题,因为它还可以更好地利用通常通过路由器和交换机传输的标准数据包大小。

答案 3 :(得分:1)

这是跨多个Socket.io进程共享数据的常用方法。到目前为止,您已经完成了单个进程和单个线程。我可以蹩脚地假设您可以选择任何提到的技术来传达共享数据,而不会遇到任何性能问题。

如果您只需要IPC,那么您可以查看Faye。但是,如果您需要保留一些数据,则可以使用与CPU相同数量的Redis主机启动Redis群集,但这会为Pub / Sub添加较小的网络噪音。