聊天/系统通信应用程序(Nodejs + RabbitMQ)

时间:2016-06-02 13:02:41

标签: node.js sockets rabbitmq chat cluster-computing

所以我目前有一个运行NodeJS的聊天系统,它通过兔子传递消息,每个连接的用户都有自己的唯一队列,订阅并只收听消息(仅限于他们)。后端还可以使用此聊天管道来传达其他系统消息,如通知/好友请求和其他用户事件驱动的信息。

目前,即使消息的有效负载与1000个用户相同,后端也必须循环并每个用户逐个发布每条消息1。我想摆脱这种情况,并能够向多个不同的用户发送相同的消息,但不能每个用户。

(例如:通知某些用户他们的朋友已上线)。

我考虑实现一个兔子队列系统,其中所有消息都汇集到同一个队列中,而不是兔子发送所有用户队列节点接收这些消息,并通过套接字连接(对任何在线的人)向适当的用户发出消息。 / p>

Proposed - infrastructure

这样,后端不需要为100和1000个用户循环,并且可以发送包含此消息应该去的所有用户的单个有效负载。我计划将nodejs服务器聚集在一起。

我也想知道,因为我从未在生产环境中这样做,我是否需要跟踪每个socketID。

到目前为止我发现的潜在缺陷:

  • 较慢,因为1000条消息可以堆积在一个队列中。
  • 手动存储套接字ID以手动传送给用户。
  • 将路由卸载到NodeJS而不是RabbitMQ

以前有人做过这样的事吗?如果是这样,你的建议是什么?是否可以使用用户唯一队列进行扩展,或将所有用户的所有分组消息汇集到较小(但较大的池)的队列中。

1 个答案:

答案 0 :(得分:1)

作为一般规则,每用户队列是一种反模式。有一些有效的用途,但我从来没有看到它是一个好主意的聊天应用程序(尽管使用这个例子的所有演示)

RabbitMQ可以成为促进系统之间消息传递的一个很好的工具,but it shouldn't be used to push messages to users

  

我考虑实现一个兔子队列系统,其中所有消息都汇集到同一个队列中,而不是兔子发送所有用户队列节点接收这些消息并通过套接字连接向适当的用户发出消息(对于任何人而言)在线)。

这是朝着正确的方向前进,但你必须记住RabbitMQ不是一个数据库(再次参见上一个链接)。

您无法随机查找位于队列中的特定消息,然后将其留在那里。他们先进先出。

在聊天应用中,我会让rabbitmq处理您系统之间的消息传递,但不会涉及向用户传递。

您对使用网络套接字的想法将成为您想要的方向。或者是Server Sent Events

如果您需要持久化消息(历史记录,搜索,上次查看的位置等),请使用数据库。保留用户停止的时间戳或其他标记,并从该位置开始向他们发送消息。

您对用户跟踪套接字的担忧绝对值得思考。

如果您的节点服务器的多个实例运行的套接字连接了不同的用户,那么您需要知道哪些用户连接到哪个节点服务器。

这可能是rabbitmq的一个很好的用例 - 但不是以每用户队列的方式。而是在每个用户的绑定中。您可以让每个节点服务器创建一个队列,以便从发布消息的交换机接收消息。然后,节点服务器将根据登录到该特定节点服务器的用户ID在交换和队列之间创建绑定

但是,这可能导致rmq中的大量绑定。

您可能需要一种更智能的方法来跟踪哪个服务器与哪些用户连接,或者只是完全忽略它并将每条消息广播到每个节点服务器。在这种情况下,每个服务器将根据消息应该传递给谁来通过websocket发布事件。

如果您使用足够智能的websocket库,它只会将消息发送给需要它的人。我知道socket.io做到了这一点,并且我确信其他的websocket库也是这样聪明的。

...

我可能没有给你一个具体的答案来解决你的情况,我确信你有更多的背景需要考虑。希望这会让你走上正确的道路。