【问题标题】:Horizontal scaling and GraphQL within a Node.js environmentNode.js 环境中的水平缩放和 GraphQL
【发布时间】:2018-10-12 12:23:37
【问题描述】:

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

an article 中,我读到可以使用带有“订阅”的 GraphQL 构建实时应用程序,除此之外,它使用起来很简单,并且具有最小化往返对象检索的优点,因此更少的资源使用。

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

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

【问题讨论】:

    标签: node.js graphql socketcluster


    【解决方案1】:

    很快 - 是的。我们已经做到了,而且效果很好。

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

    为了实现它,我们使用了排队系统,即RabbitMQ

    想象一下这种报告生成场景,这可能需要 10 分钟:

    1. 客户端通过 WebSocket 连接到我们的 GraphQL API(实例 1)
    2. 客户端通过 WebSocket 发送命令生成报告
    3. API 为命令生成令牌并将生成报告的命令放入 CommandQueue(在 RabbitMQ 中),将令牌返回给客户端。
    4. 客户端使用令牌订阅其命令结果的事件
    5. 某个后端 Worker 接收命令并执行报告生成过程
    6. 在此期间 GraphQL API(实例 1)死亡
    7. 客户端自动重新连接到 GraphQL API(实例 2)
    8. 客户端使用之前获取的令牌续订订阅
    9. Worker 完成,EventsQueue (RabbitMQ) 上的结果
    10. 我们所有的 GraphQL 实例都会在 ReportGenerationDoneEvent 上接收信息,并检查是否有人在监听它的令牌。
    11. GraphQL API(实例 2)看到客户端正在等待结果。通过 websocket 推送结果。
    12. GraphQL API(实例 3-100)忽略 ReportGenerationDoneEvent

    它相当广泛,但通过简单的抽象,您不必考虑所有这些复杂性,并为使用此路由的新进程编写跨多个服务的大约 30 行代码。

    它的精彩之处在于,您最终获得了不错的水平扩展、事件可重放性(重试)、关注点分离(客户端、api、worker),尽可能快地将数据推送到客户端,并且随着您提到您不会在 are we done yet? 请求上浪费带宽。

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

    关于 SocketCluster 的好想法。它将优化上述场景中的第 10 步,但目前,我们没有看到将 ReportGenerationDoneEvent 广播到整个 API 集群的任何性能问题。对于更多实例或多区域架构,这将是必须的,因为它可以实现更好的扩展和分片。

    理解 SocketCluster 运行在通信层(WebSockets)很重要,但逻辑 API 层(GraphQL)在此之上。要进行 GraphQL 订阅,您只需使用允许您向用户推送信息的通信协议,而 WebSockets 允许这样做。

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

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

    【讨论】:

    • 感谢您的回复。好好理解一下:当你说通过 Websocket 使用 GraphQL API 时,你的意思是你通过 Websocket 发起一个套接字连接,然后处理与 GraphQL 的数据交换?我对这些技术还是新手,所以如果我错了,请纠正我:GraphQL 订阅和 WebSocket 连接不是等效的吗?如果不用于扩展和分片,将 GraphQL 与 SocketCluster 一起使用有什么好处?
    • 当您将项目配置为使用 WebSockets 时,理论上您可以放弃所有 HTTP GraphQL 请求而只使用 WebSockets 进行通信。要进行 GraphQL 订阅,您只需使用允许您向用户推送信息的通信协议,而 WebSockets 允许这样做。所以它们不是等价的,它们在不同的层次上运行——GQL 订阅在更高层次的逻辑层上,它使用 WebSocket 来传输数据。此外,使用 SocketCluster 主要是为您提供刚才所说的 - 缩放和分片。
    • 在结合 REST 和 Websockets 设计(参见问题 stackoverflow.com/a/43971625/5486116)中,许多人建议实施一个解决方案,我们仅在需要时订阅更改。我认为这个解决方案消耗更少的资源并提供更好的性能......如果我们想在将 Websockets 与 GraphQL 结合使用时应用相同的逻辑怎么办:我们主要通过 Websocket (SocketCluster) 进行通信,对于任何数据交换我们使用 GraphQL,并且当然 SocketCluster 将主要负责可扩展性和分片部分。这是一个好的设计吗?
    • 我认为这是一个不错的设计选择,但请记住迭代实现。仅当您计划在任何单个时间点打开多个套接字时才使用 SocketCluster。也可以,你应该只在必要时订阅,因为 WebSocket 是有状态的,需要管理和心跳。
    • 再次感谢您的指导。您如何看待在您的答案中添加摘要以便更多人可以从您在 cmets 中告诉我的内容中受益?
    猜你喜欢
    • 2015-05-11
    • 2019-01-01
    • 2015-09-20
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    相关资源
    最近更新 更多