Cloud Supergraphs 中的 GraphQL 订阅
在您的各项服务中实时交付数据
云supergraph 对 GraphQL 订阅支持目前处于 预览。
您还可以使用 订阅与企业自托管 supergraph 一起使用。请参阅 GraphOS 路由器文档。
云 supergraphs 为 GraphQL 订阅 操作 提供 预览支持:
subscription OnStockPricesChanged {stockPricesChanged {symbolprice}}
使用云图超级图,您可以向任何支持订阅
字段 的子图架构中添加graphql-transport-ws
WebSocket 协议:
type Subscription {stockPricesChanged: [Stock!]!}
然后,客户端可以执行订阅在您的云路由器上,它会在您的子图上执行。
ⓘ 注意
要使用云supergraph的订阅,您必须首先完成某些先决条件。
订阅是用来做什么的?
GraphQL 订阅使客户端能够在有新数据可用时接收持续、实时的更新。与查询和突变不同,订阅是持久的。这意味着一个客户端可以接收单个订阅的多个更新:
订阅非常适合依赖频繁变化、时间敏感性数据的应用程序,例如股价、物联网传感器读数、实时聊天或体育得分。
订阅如何工作
客户端在HTTP上执行GraphQL 订阅 操作对您的路由器:
示例订阅subscription OnStockPricesChanged {stockPricesChanged {symbolprice}}- 客户端不使用WebSocket协议。相反,它通过multipart HTTP响应。
- 通过使用HTTP进行订阅,客户端可以在HTTP上执行所有GraphQL 操作类型,而不是使用两种不同的协议。
- Apollo Client, Apollo Kotlin, 以及 Apollo iOS 都支持通过 HTTP 进行最小化配置的 GraphQL 订阅。请参阅每个库的文档以了解详细信息。 Apollo Client 还为 Relay 和 urql 库提供了网络适配器。
当你的 router 收到订阅时,它会针对定义请求 字段 的相应
subgraph
执行相同的订阅操- 这种通信通常使用 WebSocket 子协议,以兼容大多数 subgraph 库。
- 使用 自托管路由器,你还可以配置一个 基于 HTTP 回调的协议.
subgraph 定期向你的 router 发送新数据。每次它这样做时,路由器都会在额外的 HTTP 响应部分中返回该数据。
- 一个订阅
可以包含在
实体 字段
这些字段定义在其他
子图.如果包括,则
路由器首先通过
查询对应子图中的
图表中上面的
投资组合子图.这些查询通常使用HTTP。
- 一个订阅
💡 提示
预备知识
在向您的订阅
字段
添加
子图之前,请按照以下顺序执行所有这些操作以防止错误:
确保您已
创建了一个云超级图并将您的
GraphQL API连接到它!更新您的超级图构建管道以使用
Apollo Federation 2.4或更高版本。- Apollo Federation
旧版本不支持
订阅
操作。
- Apollo Federation
如果您的
子图架构
指定了
Apollo Federation
版本,请修改它们以使用Apollo Federation 2.4或更高版本:stocks.graphqlextend schema@link(url: "https://specs.apollo.dev/federation/v2.4"import: ["@key", "@shareable"])type Subscription {stockPricesChanged: [Stock!]!}- 您可以跳过修改没有定义任何
订阅
字段的
子图架构。
- 您可以跳过修改没有定义任何
在每个订阅的
子图中。
确保子图使用graphql-transport-ws
WebSocket协议进行
订阅。在每个订阅的
子图中。
确保子图在/ws
路径上托管
其订阅WebSocket端点。- 如果您的WebSocket端点当前托管在不同的路径上,您可以
/ws
作为额外的路径添加,而不是删除原始路径。
- 如果您的WebSocket端点当前托管在不同的路径上,您可以
部署您的更新
子图。
完成这些先决条件后,您开始在
在您的云路由器上执行
订阅.
默认配置
订阅
对于
GraphOS Cloud
自动启用,以下为默认
路由器
配置:
subscription:enabled: truemode:passthrough:all:path: /ws
示例执行
假设我们的超级图包含以下子图和部分模式:
type Product @key(fields: "id") {id: ID!name: String!price: Int!}type Subscription {productPriceChanged: Product!}
type Product @key(fields: "id") {id: ID!reviews: [Review!]!}type Review {score: Int!}
客户端可以对我们的路由器执行以下订阅:
subscription OnProductPriceChanged {productPriceChanged {# Defined in Products subgraphnamepricereviews {# Defined in Reviews subgraph!score}}}
当我们的路由器接收到这个操作时,它将在产品子图上执行相应的订阅操作(通过新的WebSocket连接):
subscription {productPriceChanged {id # Added for entity fetchingnameprice# Reviews fields removed!}}
ⓘ 注意
- 这个操作为
Product.id
字段添加了@key
字段。要合并来自不同子图的实体字段,路由器需要Product
实体的键字段。 - 此操作移除了在评论子图中定义的所有字段,因为产品子图无法解析它们。
在订阅开始后的任何时间点,产品子图可能会将更新数据发送到我们的路由器。每当这种情况发生时,路由器不会立即将此数据返回给客户端,因为它缺失了来自评论子图的所需字段!
相反,我们的路由器会对评论子图执行标准GraphQL查询来获取缺失的实体字段:
query {_entities(representations: [...]) {... on Product {reviews {score}}}}
从评论子图收到此查询结果后,我们的路由器将其与产品数据结合,并将组合结果返回给订阅的客户端。
使用 curl
测试订阅
为了快速测试HTTP-based订阅而不设置Apollo Client库,你可以在格式如下的情况下使用curl
命令针对你的云路由器执行命令:
curl 'https://main--my-org-supergraph.apollographos.net/graphql' -v \-H 'accept: multipart/mixed; boundary="graphql"; subscriptionSpec=1.0, application/json' \-H 'content-type: application/json' \--data-raw '{"query":"subscription OnProductPriceChanged { productPriceChanged { name price reviews { score } } }","operationName":"OnProductPriceChanged"}'
该命令创建一个 HTTP 多部分请求并保持一个开放连接,以多部分响应接收新的 订阅 数据:
--graphqlcontent-type: application/json{}--graphqlcontent-type: application/json{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":400,"reviews":[{"score":5}]}}}}--graphqlcontent-type: application/json{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":375,"reviews":[{"score":5}]}}}}--graphqlcontent-type: application/json{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":425,"reviews":[{"score":5}]}}}}--graphql--