Node.js环境中的水平扩展和GraphQL

时间:2018-05-02 11:41:31

标签: node.js graphql socketcluster

我正在尝试构建一个包含即时消息传递模块的应用程序,其中一个主要挑战是无论用户数量或交换的消息是什么,都可以保持应用程序的可扩展性。

an article中我读到可以使用带有“订阅”的GraphQL构建实时应用程序,除此之外,它是一个简单易用的protocole,并且具有最小化往返对象检索的优势,因而使用资源较少。

但是,如果我们需要向系统添加新的服务器/节点以便水平扩展呢?这可能是使用GraphQL吗?

以允许水平扩展的websockets实现为例,有SocketCluster。我想知道GraphQL开发的应用程序是否可以跨多个节点/机器进行扩展,或者它必须与SocketCluster等其他框架一起使用才能实现这一目标。

1 个答案:

答案 0 :(得分:3)

很快 - 是的。我们已经做到了,它运作良好。

诀窍是,在涉及水平扩展时,您必须更深入地思考API工作者应用程序。如果您想要推送架构,则从一开始就需要异步

为实现这一目标,我们使用排队系统,即 RabbitMQ

想象一下这种报告生成方案,最多可能需要10分钟:

  1. 客户端通过WebSocket
  2. 连接到我们的GraphQL API(实例1)
  3. 客户端发送命令以通过WebSocket生成报告
  4. API为命令生成令牌,并将命令放入CommandQueue中生成报告(在RabbitMQ中),将令牌返回给客户端。
  5. 客户使用令牌
  6. 订阅其命令结果的事件
  7. 某些后端工作人员接收命令并执行报告生成过程
  8. 在此期间,GraphQL API(实例1)死亡
  9. 客户端自动重新连接到GraphQL API(实例2)
  10. 客户使用之前获得的令牌续订订阅
  11. 工作人员已完成,结果发生在EventsQueue(RabbitMQ)
  12. 我们所有的GraphQL实例都会收到有关ReportGenerationDoneEvent的信息,并检查是否有人正在侦听其令牌。
  13. GraphQL API(实例2)看到客户端正在等待结果。通过websockets推送结果。
  14. GraphQL API(实例3-100)忽略ReportGenerationDoneEvent
  15. 它有点广泛,但是通过简单的抽象,您不必考虑所有这些复杂性,并使用此路由为多个服务编写约30行代码。

    关于它的精彩之处,你最终得到了良好的横向扩展,事件可重放性(重试),关注点分离(客户端,api,工作者),尽快将数据推送到客户端,以及当你提到你不要在are we done yet?请求上浪费带宽。

    另一个很酷的事情是,只要用户在我们的面板中打开报告列表,他就会看到当前正在生成报告,并且可以订阅他们的更改,因此他们不必手动刷新列表。

    很好地思考SocketCluster。它将优化上述方案中的步骤10,但就目前而言,我们看不到将ReportGenerationDoneEvent广播到整个API群集的任何性能问题。对于更多实例或多区域架构,它将是必须的,因为它将允许更好的缩放和分片。

    重要的是要了解SocketCluster在通信层(WebSockets)上运行,但逻辑API层(GraphQL)高于该层。要进行GraphQL订阅,您只需使用允许您将信息推送给用户的通信协议,而WebSockets允许这样做。

    我认为使用SocketCluster是一个很好的设计选择,但请记住迭代实现。当您计划在任何单个时间点打开许多套接字时,仅使用SocketCluster。此外,您应该仅在必要时订阅,因为WebSocket是有状态的并且需要管理和心跳。

    如果您对我上面使用的异步后端架构更感兴趣,请阅读CQRS和事件源模式。