学习教程
订阅

订阅

¥Subscriptions

Learn how to get real-time updates from a GraphQL server

除了使用无状态查询和变异操作读取和写入数据之外,GraphQL 规范还描述了如何通过长寿命请求接收实时更新。在此页面上,我们将探索客户端如何使用订阅操作订阅 GraphQL 服务器上的事件详细信息。

¥In addition to reading and writing data using stateless query and mutation operations, the GraphQL specification also describes how to receive real-time updates via long-lived requests. On this page, we’ll explore how clients can subscribe to details of events on a GraphQL server using subscription operations.

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

¥Many of the features of GraphQL operations that apply to queries also apply to subscriptions, so review the Queries page first before proceeding.

订阅更新

¥Subscribing to updates

订阅字段的定义与 QueryMutation 字段完全相同,但使用 subscription 根操作类型:

¥Subscription fields are defined exactly as Query and Mutation fields are, but using the subscription root operation type instead:

type Subscription {
  reviewCreated: Review
}

类似地,使用 subscription 关键字作为操作类型启动订阅:

¥Similarly, a subscription is initiated using the subscription keyword as the operation type:

subscription NewReviewCreated {
  reviewCreated {
    rating
    commentary
  }
}

GraphQL 订阅通常由单独的发布/订阅系统支持,以便可以在运行时根据需要发布有关更新数据的消息,然后由 API 中订阅字段的解析器函数使用。

¥GraphQL subscriptions are typically backed by a separate pub/sub system so that messages about updated data can be published as needed during runtime and then consumed by the resolver functions for the subscription fields in the API.

对于前面的示例,我们可以想象当客户端提交具有 createReview 变异的新评论时,将 REVIEW_CREATED 消息发布到发布/订阅系统,然后在 reviewCreated 订阅字段的解析器函数中监听此事件,以便服务器可以将此数据发送给订阅的客户端。

¥For the previous example, we could imagine publishing a REVIEW_CREATED message to a pub/sub system when a client submits a new review with the createReview mutation, and then listening for this event in the resolver function for the reviewCreated subscription field so that the server may send this data to subscribed clients.

请注意,订阅不同于实时查询的概念,实时查询是某些 GraphQL 实现可能提供的一种松散定义的功能。在此处阅读有关实时查询正式规范的持续讨论的更多信息。

¥Note that subscriptions are different from the concept of live queries, a loosely defined feature that some GraphQL implementations may offer. Read more about the ongoing discussion on a formal specification for live queries here.

与查询和变异操作一样,GraphQL 没有指定要使用的传输协议,因此由服务器决定。实际上,你经常会看到它们是使用 WebSockets 或服务器发送的事件实现的。想要发送订阅操作的客户端也需要支持所选协议。有社区维护的规范,用于使用 WebSockets服务器发送的事件 实现 GraphQL 订阅。

¥As with query and mutation operations, GraphQL doesn’t specify what transport protocol to use, so it’s up to the server to decide. In practice, you will often see them implemented with WebSockets or server-sent events. Clients that want to send subscription operations will also need to support the chosen protocol. There are community-maintained specifications for implementing GraphQL subscriptions with WebSockets and server-sent events.

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

¥One important distinction to make with subscription operations is that a document may contain a number of different subscription operations with different root fields, but each operation must have exactly one root field.

例如,此操作无效:

¥For example, this operation would be invalid:

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

但这个文档是有效的:

¥But this document is valid:

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

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

¥As with query and mutation operations, the document above contains multiple operations so each operation must be named, and the name of the operation to execute must be specified in the request.

大规模使用订阅

¥Using subscriptions at scale

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

¥Subscription operations are a powerful feature of GraphQL, but they are more complicated to implement than queries or mutations because you must maintain the GraphQL document, variables, and other context over the lifetime of the subscription. These requirements can be challenging when scaling GraphQL servers horizontally because each subscribed client must be bound to a specific instance of the server.

类似地,客户端库通常需要更高级的功能来处理这些类型的操作,例如,如果连接中断,则重新订阅操作的逻辑或处理初始查询和更新的订阅数据之间的潜在竞争条件的机制。

¥Similarly, client libraries will typically need more advanced features to handle these kinds of operations, such as logic to resubscribe to operations if the connection is disrupted or mechanisms to handle potential race conditions between initial queries and updated subscription data.

实际上,支持订阅的 GraphQL API 将需要比仅公开查询和变异字段的架构更复杂的架构。此架构的设计方式将取决于特定的 GraphQL 实现、哪个发布/订阅系统支持订阅、所选的传输协议,以及与实时数据的可用性、可扩展性和安全性相关的其他要求。

¥In practice, a GraphQL API that supports subscriptions will call for a more complicated architecture than one that only exposes query and mutation fields. How this architecture is designed will depend on the specific GraphQL implementation, what pub/sub system supports the subscriptions, and the chosen transport protocol, as well as other requirements related to availability, scalability, and security of the real-time data.

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

¥Subscription operations are well suited for data that changes often and incrementally, and for clients that need to receive those incremental updates as close to real-time as possible to deliver the expected user experience. For data with less frequent updates, periodic polling, mobile push notifications, or re-fetching queries based on user interaction may be the better solutions for keeping a client UI up to date.

后续步骤

¥Next steps

回顾我们学到的关于模式和类型的知识:

¥To recap what we’ve learned about subscriptions:

  • GraphQL 订阅操作可用于通过长寿命请求进行增量数据更新

    ¥GraphQL subscription operations can be used for incremental data updates via long-lived requests

  • 订阅操作通常由有状态传输协议支持,因此与查询和突变相比,它们需要更多的努力来实现和支持

    ¥Subscription operations are typically supported by a stateful transport protocol, so they will require more effort to implement and support than queries and mutations

  • 需要将频繁和增量更新流式传输到客户端的数据获取用例最适合订阅

    ¥Data-fetching use cases that require frequent and incremental updates to be streamed to a client are best suited for subscriptions

现在我们已经介绍了 GraphQL 中的所有三种操作类型,让我们来探索 GraphQL 服务器如何对客户端请求进行 validated

¥Now that we’ve covered all three operation types in GraphQL, let’s explore how client requests are validated by a GraphQL server.