【问题标题】:Horizontally scaling an application that shares input between servers水平扩展在服务器之间共享输入的应用程序
【发布时间】:2014-02-02 14:10:09
【问题描述】:

我正在构建一个通过 websocket 接受输入的应用程序,该应用程序必须共享回可能连接到其他前端服务器的其他客户端。

为简单起见,想象一个多用户多房间聊天应用程序。将输入路由到正确的连接不是问题,它是服务器之间的消息传递,并且能够扩展它并控制消息的延迟。

现在我有一个每个前端都连接到的代理进程,然后他们订阅一个队列以获取其连接可能需要知道的任何信息。这样做是为了切断从代理接收的消息,这些消息永远不会被前端使用。但是,我仍然收到大约 75% 到 85% 的消息从代理发送回每个前端。

在旅途中,我正在做消息验证、解析和任何其他业务逻辑工作。在旅途中,我在本地数组上循环订阅并将消息发送到每个订阅的连接。

举个例子:如果我在 11 台前端服务器上收到 10 条消息,大约是 110 条消息 - 10 条消息在本地处理,而不由代理发回)* 0.75 乐观订阅级别 = 75 条消息被发送回每个服务器要处理。所以我们有 10 个本地 + 75 个代理 = 每个服务器在这段时间内处理 85 条消息。

现在我不会有 11 台前端服务器,速度为 100 msg/秒,也许两个,但代理进程发送回每个前端服务器的消息似乎会爆炸,因为我在其他前端服务器上收到的消息越多。

代理进程是一个与 RabbitMQ 和 PostgreSQL 对话的小型 node.js 应用程序。前端服务器也是 node.js 应用程序。

我可以做些什么或应该做些什么来在高音量期间保持低延迟?

更新以回复用户评论:虽然我预计队列之间会有很多重叠,但连接会导致他们的前端服务器订阅我不希望每个服务器都达到 100%。最坏的情况是每个前端服务器都必须订阅代理上的每个队列,从而从代理获得 100% 的消息。乐观地说,真正需要将大约 75% 的消息发送回任何特定的前端服务器。

itaifrenkel 的第二次更新:两个用户发送的消息可能会以不同的顺序返回。只有当延迟非常低并且它只发生在彼此非常接近的消息发送时才可以接受。如果它发生在消息相隔几秒钟的情况下,那么我会说我们在延迟和规模方面存在问题。

在某些情况下,我们需要显示历史记录,但我忽略了它,因为我觉得它超出了问题的范围。

【问题讨论】:

  • 您说无论是否使用消息,开销都是 75%。那你为什么用这么乐观的订阅。不应该严格按照使用基础。您如何决定是否订阅。
  • 如果聊天室拥挤,同一个聊天室的两个用户看到两条消息的顺序不同是否有效?
  • 当用户登录聊天室时,在用户登录前提供历史消息会有什么好处吗?

标签: node.js rabbitmq scalability latency


【解决方案1】:

消息队列解决方案听起来像是正确的选择。正如您在标题中所建议的那样,要扩展它,您需要横向移动。

我没有使用过 RabbitMQ,所以我无法用细节让你大吃一惊,但水平扩展意味着一个集群,所以 http://www.rabbitmq.com/clustering.html 可能足以让你继续前进。

【讨论】:

    【解决方案2】:

    假设每个用户在任何时候都只连接到一个聊天室。这意味着一个 websocket 连接 = 一个聊天室。因此,您将编写一个额外的 node.js 反向代理,它将每个用户连接转发到“前端”node.js 进程,该进程很可能已经在侦听该聊天室的事件(聊天室亲和性使用基于聊天室 ID)。这种路由算法需要尽最大努力提高网络利用率,不需要完美。

    现在让我们允许每个用户在多个聊天室中。然后,您需要改进反向代理以连接到多个“前端”服务器并将结果多路复用回给用户。

    这种设计将以网络延迟为代价提供水平可扩展性。

    注意:当然,新的反向代理现在是前端服务器,但是当我提到“前端”时,我指的是您在问题中描述的服务器。

    【讨论】:

      猜你喜欢
      • 2019-12-01
      • 2021-05-25
      • 1970-01-01
      • 2018-07-12
      • 2013-10-17
      • 2019-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多