订阅 (Subscriptions)

了解如何从 GraphQL 服务器获取实时更新

除了使用无状态的查询(Query)和变更(Mutation)操作读写数据外,GraphQL 规范还描述了如何通过长连接请求接收实时更新。在此页面中,我们将探讨客户端如何使用订阅操作来订阅 GraphQL 服务器上的事件详情。

适用于查询的许多 GraphQL 操作特性也适用于订阅,因此在继续之前,请先查看查询 (Queries)页面。

订阅更新

订阅字段的定义方式与 QueryMutation 字段完全相同,但改用 subscription 根操作类型。

type Subscription {
  reviewCreated: Review
}

同样,订阅也是使用 subscription 关键字作为操作类型来发起的。

subscription NewReviewCreated {
  reviewCreated {
    rating
    commentary
  }
}

GraphQL 订阅通常由一个独立的发布/订阅(pub/sub)系统支持,以便在运行时根据需要发布有关更新数据的消息,然后由 API 中订阅字段的解析器函数(resolver functions)进行消费。

以前面的例子为例,我们可以想象当客户端通过 createReview 变更提交新评价时,向发布/订阅系统发布一条 REVIEW_CREATED 消息,然后在 reviewCreated 订阅字段的解析器函数中监听此事件,以便服务器可以将此数据发送给已订阅的客户端。

请注意,订阅与“实时查询”(live queries)的概念不同,后者是一些 GraphQL 实现可能提供的松散定义的特性。点击此处阅读更多关于实时查询正式规范的持续讨论。

与查询和变更操作一样,GraphQL 并没有规定使用哪种传输协议,这由服务器决定。在实践中,你经常会看到它们使用 WebSockets 或服务器发送事件(SSE)来实现。想要发送订阅操作的客户端也需要支持所选的协议。社区维护了使用 WebSockets服务器发送事件 实现 GraphQL 订阅的规范。

关于订阅操作的一个重要区别是,一个文档可能包含许多具有不同根字段的订阅操作,但每个操作必须且仅能有一个根字段。

例如,这个操作是无效的:

subscription {
  reviewCreated {
    rating
    commentary
  }
  humanFriendsUpdated {
    name
    friends {
      name
    }
  }
}

但这个文档是有效的:

subscription NewReviewCreated {
  reviewCreated {
    rating
    commentary
  }
}
subscription FriendListUpdated($id: ID!) {
  humanFriendsUpdated(id: $id) {
    name
    friends {
      name
    }
  }
}

与查询和变更操作一样,上面的文档包含多个操作,因此每个操作必须命名,并且必须在请求中指定要执行的操作名称。

在大规模场景下使用订阅

订阅操作是 GraphQL 的一项强大功能,但实现起来比查询或变更更复杂,因为你必须在订阅的整个生命周期内维护 GraphQL 文档、变量和其他上下文。当水平扩展 GraphQL 服务器时,这些要求可能会带来挑战,因为每个订阅的客户端必须绑定到服务器的特定实例。

同样,客户端库通常需要更高级的功能来处理此类操作,例如在连接中断时重新订阅操作的逻辑,或处理初始查询与更新的订阅数据之间潜在竞态条件的机制。

在实践中,支持订阅的 GraphQL API 比仅暴露查询和变更字段的 API 需要更复杂的架构。该架构的设计取决于具体的 GraphQL 实现、支持订阅的发布/订阅系统、所选的传输协议,以及与实时数据的可用性、可扩展性和安全性相关的其他要求。

订阅操作非常适合于频繁且增量更改的数据,以及需要尽可能接近实时地接收这些增量更新以提供预期用户体验的客户端。对于更新频率较低的数据,定期轮询、移动推送通知或基于用户交互重新获取查询可能是保持客户端 UI 更新的更好解决方案。

后续步骤

回顾一下我们学到的关于订阅的内容:

  • GraphQL 订阅操作可用于通过长连接请求进行增量数据更新。
  • 订阅操作通常由有状态的传输协议支持,因此实现和维护它们比查询和变更需要更多的精力。
  • 需要向客户端流式传输频繁且增量更新的数据获取场景最适合使用订阅。

现在我们已经涵盖了 GraphQL 中的所有三种操作类型,让我们来探索 GraphQL 服务器如何验证客户端请求。

下一课

验证

了解 GraphQL 如何通过验证规则确保查询的正确性,以及如何及早检测常见错误。

前往下一课 教程