10月8日至10日加入我们,在纽约市学习关于 GraphQL 联盟和 API 平台工程的最新技巧、趋势和新闻。加入我们参加 2024 年纽约市 GraphQL Summit
文档
免费开始
您正在查看该软件上一个版本的文档。 切换到最新稳定版本。

持久化查询

最小化请求延迟的同时确保图形安全


Apollo支持两个独立但相关的功能,称为自动持久查询)和持久查询。两者结合,客户端可以通过发送操作ID而不是整个操作字符串来执行操作。是整个操作字符串的哈希值。

默认使用HTTP发送哈希查询GET而不是默认的POST,这使得它们更容易在网络边缘缓存。

持久查询与APQs之间的差异

功能需要将注册到持久查询列表)中。这使得PQL可以作为由您的其他应用程序创建的操作白名单。

在使用APQs的情况下,如果服务器找不到客户端提供的操作ID,则服务器返回一个错误,表明它需要完整的操作字符串。如果收到此错误,它会自动使用完整的操作字符串重新尝试操作。

如果只想提高请求延迟和带宽使用,可以解决您的用例。如果您还使用进行操作白名单,应该将操作注册到PQL

有关持久查询和GraphOS持久查询文档中的差异的更多详细信息。

实现步骤

持久查询和APQs都需要您配置客户端的请求方式。如果您打算使用持久查询进行白名单,您还需要生成和发布一个操作清单。

在实现时,我们建议您遵循以下顺序

实现步骤是否需要PQs?是否需要APQs?
1. 生成操作清单--
2. 将操作清单发布到PQL--
3. 在客户端请求时启用持久查询

本文的其余部分将详细介绍这些步骤。

还要求您创建和链接一个PQL,并配置您的以接收请求。本仅描述客户端创建操作清单并发送持久化查询请求所需的步骤。有关持久化查询其他配置方面的更多信息,请参阅GraphOS持久化查询文档

0. 要求

您可以使用APQs与以下版本的和 Apollo

  • Apollo Kotlin (v1.0.0+)
  • Apollo Server (v1.0.0+)
  • Apollo Router (v0.1.0+)

注意:您可以使用Apollo ServerApollo Router进行 APQs。它们不需要一起使用。

使用持久化查询进行白名单的要求如下:

1. 生成操作清单

此步骤仅适用于使用持久化查询实施白名单。对于 APQs,此步骤不需要。

操作清单充当 Apollo Router 可以检查传入请求的受信任操作的黑白名单。要生成操作清单,请在您的 Gradle 脚本中将operationManifestFormat设置为"persistedQueryManifest"

// build.gradle.kts
apollo {
service("api") {
packageName.set("com.example")
// Enable generation of the operation manifest
operationManifestFormat.set("persistedQueryManifest")
}
}

操作清单在代码生成期间生成。每当您构建项目时,都会自动生成,也可以通过执行generateApolloSources Gradle 任务手动触发。

操作清单生成在build/generated/manifest/apollo/$serviceName/persistedQueryManifest.json,其中 $serviceName 在这里为 "api"。生成的操作清单看起来如下所示:

持久化查询描述符.json
{
"format": "apollo-persisted-query-manifest",
"version": 1,
"operations": [
{
"id": "e0321f6b438bb42c022f633d38c19549dea9a2d55c908f64c5c6cb8403442fef",
"body": "query GetItem { thing { __typename } }",
"name": "GetItem",
"type": "query"
}
]
}

2. 发布操作描述符

此步骤仅适用于使用持久化查询实施白名单。对于 APQs,此步骤不需要。

💡 提示

请确保您的版本为0.17.2或更高。之前的版本不支持将操作发布为PQL。下载最新版本。

在您生成操作描述符后,您可以使用Rover CLI将其发布到您的PQL,如下所示:

示例命令
rover persisted-queries publish my-graph@my-variant \
--manifest ./persisted-query-manifest.json
  • my-graph@my-variant 图引用,表示链接到任何所对应的PQL
    • 图引用的格式为graph-id@variant-name
  • 使用--manifest选项提供您要发布的清单文件的路径。

注意

执行持久查询发布命令时,假设清单文件以Apollo客户端工具生成的格式生成。此命令还可以支持Relay编译器生成的清单文件,通过添加--manifest-format relay 参数来实现。您的Rover CLI版本必须为0.19.0或更高版本才能使用此参数。

执行持久查询发布命令将执行以下操作:

  1. 将提供的清单文件中的所有操作发布到与指定变种或指定的PQL链接的PQL

    • 将清单发布到PQL是累加的。PQL中存在的任何现有条目都将保留。
    • 如果您将具有相同id但与PQL中现有条目不同的详细信息发布的操作,整个发布命令将会因错误而失败。
  2. 更新所有其他,以便与这些变种关联的可以获取其更新的PQL。

与生成清单一样,最好在您的CI/CD管道中执行此命令,以便将新的操作作为应用发布过程的一部分发布。提供的API密钥必须具有角色,并为本应具有Graph Admin持久化查询发布者。持久化查询发布者是一个专门用于与rover persisted-queries publish命令一起使用的角色;具有此角色的API密钥对中的图数据没有其他访问权限,并且适合与受信任的第三方客户端开发者共享,以便允许将操作发布到您的图的PQL,但不应对图进行其他访问。

测试操作

您可以发送一些测试操作来测试您是否已成功发布清单:

首先,启动您的GraphOS连接路由器:

APOLLO_KEY="..." APOLLO_GRAPH_REF="..." ./router --config ./router.yaml
2023-05-11T15:32:30.684460Z INFO Apollo Router v1.18.1 // (c) Apollo Graph, Inc. // Licensed as ELv2 (https://go.apollo.dev/elv2)
2023-05-11T15:32:30.684480Z INFO Anonymous usage data is gathered to inform Apollo product development. See https://go.apollo.dev/o/privacy for details.
2023-05-11T15:32:31.507085Z INFO Health check endpoint exposed at http://127.0.0.1:8088/health
2023-05-11T15:32:31.507823Z INFO GraphQL endpoint exposed at http://127.0.0.1:4000/ 🚀

接下来,使用curl发送POST请求,如下所示:

curl https://127.0.0.1:4000 -X POST --json \
'{"extensions":{"persistedQuery":{"version":1,"sha256Hash":"dc67510fb4289672bea757e862d6b00e83db5d3cbbcfb15260601b6f29bb2b8f"}}}'

如果您的路由器的PQL包含一个与提供的sha256Hash属性值匹配的ID的操作,则会执行相应的操作并返回其结果。

3. 在ApolloClient上启用持久化查询

一旦您已将代码生成配置为包括操作ID,您可以更新客户端以通过操作ID而不是整个操作字符串来更新查询。配置相同,无论您使用的是APQ还是持久化查询。在您的ApolloClient.Builder上调用autoPersistedQueries()

val apolloClient = ApolloClient.Builder()
.serverUrl("https://...")
.autoPersistedQueries()
.build()

一旦在您的ApolloClient上启用了APQ,默认情况下会发送哈希查询。

您可能希望禁用某些查询的,例如,以避免数据经常更新时的任何缓存。为此,请在ApolloCall上设置enableAutoPersistedQueries为false:

apolloClient.query(myQuery).enableAutoPersistedQueries(false).toFlow()

为持久化查询生成自定义ID

默认情况下,Apollo使用Sha256哈希算法来生成查询的ID。要提供自定义ID生成逻辑,请使用operationIdGenerator选项。它接受一个实现OperationIdGenerator接口(com.apollographql.apollo3.compiler.OperationIdGenerator)的instance作为输入。您可以使用此选项指定不同的哈希算法或从不同的位置获取持久化查询ID,例如,从服务或CLI。

示例MD5哈希生成器

apollo {
service("service") {
operationIdGenerator.set(object : com.apollographql.apollo3.compiler.OperationIdGenerator {
override val version = "my-md5-version1"
override fun apply(operationDocument: String, operationName: String): String {
return operationDocument.md5()
}
})
}
}
import com.apollographql.apollo3.compiler.OperationIdGenerator
apollo {
service("service") {
operationIdGenerator = new OperationIdGenerator() {
String apply(String operationDocument, String operationName) {
return operationDocument.md5()
}
/**
* Use this version override to indicate an update to the implementation.
* This forces gradle to recompile models.
*/
String version = "my-md5-v1"
}
}
}

标识符生成器版本控制

标识符生成器的结果是缓存的。当标识符生成器的实现发生变化时,缓存不会被更新。要表示标识符生成器实现的更新,根据上述示例更改 版本 覆盖。

上一页
@defer 支持(试验性)
下一页
简介
评分文章评分在GitHub上编辑Edit论坛Discord

©2024Apollo Graph Inc.,商业名称 Apollo GraphQL。

隐私策略

公司