在 Amazon AppSync 中配置服务器端缓存和 API 有效载荷压缩 - Amazon AppSync GraphQL
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

在 Amazon AppSync 中配置服务器端缓存和 API 有效载荷压缩

Amazon AppSync 的服务器端数据缓存功能在内存缓存中高速提供数据,从而提高性能并减少延迟。这减少了直接访问数据来源的需求。缓存适用于单位解析器和管道解析器。

Amazon AppSync 还允许您压缩 API 响应,以便更快地加载和下载负载内容。这可能会减轻应用程序的压力,同时还可能会降低数据传输费用。压缩行为是可配置的,您可以自行决定进行设置。

请参阅本节以帮助在 Amazon AppSync API 中定义所需的服务器端缓存和压缩行为。

实例类型

Amazon AppSync 在与您的 Amazon AppSync API 相同的 Amazon 账户和 Amazon 区域中托管 Amazon ElastiCache(Redis OSS)实例。

可以使用以下 ElastiCache(Redis OSS)实例类型:

small

1 个 vCPU、1.5 GiB RAM、低到中网络性能

medium

2 个 vCPU、3 GiB RAM、低到中网络性能

large

2 个 vCPU、12.3 GiB RAM,高达 10 Gb 网络性能

xlarge

4 个 vCPU、25.05 GiB RAM,高达 10 Gb 网络性能

2xlarge

8 个 vCPU、50.47 GiB RAM,高达 10 Gb 网络性能

4xlarge

16 个 vCPU、101.38 GiB RAM,高达 10 Gb 网络性能

8xlarge

32 个 vCPU、203.26 GiB RAM、10 Gb 网络性能(并非在所有区域中都提供)

12xlarge

48 个 vCPU、317.77 GiB RAM、10 Gb 网络性能

注意

过去,您指定了特定的实例类型(例如 t2.medium)。自 2020 年 7 月起,这些旧实例类型可以继续使用,但将弃用这些实例类型而不建议使用。我们建议您使用此处描述的通用实例类型。

缓存行为

以下是与缓存相关的行为:

没有服务器端缓存。

完整请求缓存

完全请求缓存是一种单独缓存解析器执行结果的机制。使用此设置,Amazon AppSync 会缓存请求期间调用的所有解析器的执行,每个解析器都单独缓存。每个解析器的数据都从其数据来源中检索并填入缓存,直到生存时间(TTL)到期。对于后续的 API 请求,会从缓存中返回每个特定解析器的结果。这意味着除非 TTL 已到期,否则,不会直接联系数据来源。Amazon AppSync 使用 context.argumentscontext.identity 映射的内容作为每个解析器的缓存键。

每个解析器的缓存

对于该设置,必须明确选择每个解析器以缓存响应。您可以在解析器上指定 TTL 和缓存键。您可以指定的缓存键是顶级映射 context.argumentscontext.sourcecontext.identity 以及/或者这些映射中的字符串字段。TTL 值是必需的,但缓存键是可选的。如果您未指定任何缓存键,则默认值是 context.argumentscontext.sourcecontext.identity 映射内容。

例如,您可以使用以下组合:

  • context.argumentscontext.source

  • context.argumentscontext.identity.sub

  • context.arguments.idcontext.arguments.InputType.id

  • context.source.idcontext.identity.sub

  • context.identity.claims.username

在您仅指定 TTL 而没有指定缓存键时,解析器的行为与完整请求缓存相同。

操作级别缓存

操作级别缓存将整个 GraphQL 查询操作响应作为一个整体进行存储。启用后,系统会缓存成功的查询响应,直至其 TTL 到期,可缓存的最大响应大小为 15 MB。对于后续使用相同缓存键的查询请求,在 TTL 未过期之前,响应将直接从缓存中提供,而不会执行任何解析器。

操作级别缓存的缓存键使用以下各项的组合生成:

  • 请求的 JSON 有效载荷中的某些属性:

    • query 字符串

    • operationName 字符串

    • variables 映射

  • context.identity 映射(不包括 context.identity.sourceIp IAM 和 Amazon Cognito 请求)

  • context.request.headers 映射(不包括下一节中列出的某些保留标头)

请求使用的授权类型也会影响缓存键。对于 IAM 授权的请求,缓存键还将包括允许和拒绝资源的列表。对于 Lambda 授权的请求,缓存键还将包括拒绝字段的列表。

缓存键将考虑在 context.request.headers 中找到的所有请求标头,但以下保留标头除外,这些标头通常是特定请求所独有的:

  • authorization

  • cloudfront-forwarded-proto

  • cloudfront-is-desktop-viewer

  • cloudfront-is-mobile-viewer

  • cloudfront-is-smarttv-viewer

  • cloudfront-is-tablet-viewer

  • cloudfront-viewer-asn

  • cloudfront-viewer-country

  • content-length

  • host

  • priority

  • sec-ch-ua

  • sec-ch-ua-mobile

  • sec-ch-ua-platform

  • via

  • x-amz-cf-id

  • x-amz-date

  • x-amz-security-token

  • x-amzn-appsync-is-vpce-request

  • x-amzn-remote-ip

  • x-amzn-requestid

  • x-amzn-trace-id

  • x-forwarded-for

缓存生存时间

该设置定义在内存中存储缓存条目的时间。最大 TTL 为 3,600 秒(1 小时),之后自动删除条目。

缓存加密

当您使用 Amazon AppSync 的服务器端数据缓存功能时,将始终为新缓存启用静态加密和传输中加密,并且无法禁用。

要对现有 API 缓存启用加密,请删除缓存,然后重新创建缓存。

要使缓存条目无效,您可以使用 Amazon AppSync 控制台或 Amazon Command Line Interface (Amazon CLI) 进行刷新缓存 API 调用。

有关更多信息,请参阅 Amazon AppSync API 参考中的 ApiCache 数据类型。

缓存逐出

在您设置 Amazon AppSync 的服务器端缓存时,您可以配置最大 TTL。该值定义在内存中存储缓存条目的时间。在必须从缓存中删除特定条目的情况下,您可以在解析器的请求或响应中使用 Amazon AppSync 的 evictFromApiCache 扩展实用程序。(例如,如果数据来源中的数据发生变化,并且缓存条目现已过时。) 要从缓存中逐出某个项目,您必须知道该项目的键。因此,如果您必须动态逐出项目,我们建议使用每个解析器的缓存,并明确定义一个用于将条目添加到缓存的键。

逐出缓存条目

要从缓存中逐出项目,请使用 evictFromApiCache 扩展实用程序。指定类型名称和字段名称,然后提供一个键值项目对象以构建要逐出的条目的键。在该对象中,每个键表示 context 对象中的一个有效条目,该条目在缓存解析器的 cachingKey 列表中使用。每个值是用于构建键值的实际值。您必须按照与缓存解析器的 cachingKey 列表中的缓存键相同的顺序,将项目放入对象中。

例如,请参阅以下架构:

type Note { id: ID! title: String content: String! } type Query { getNote(id: ID!): Note } type Mutation { updateNote(id: ID!, content: String!): Note }

在该示例中,您可以启用每个解析器的缓存,然后为 getNote 查询启用该功能。接下来,您可以将缓存键配置为由 [context.arguments.id] 组成。

在您尝试获取 Note 以构建缓存键时,Amazon AppSync 使用 getNote 查询的 id 参数在其服务器端缓存中执行查找。

在您更新 Note 时,您必须逐出特定注释的条目,以确保下一个请求从后端数据来源中获取该注释。为此,您必须创建一个请求处理程序。

以下示例说明了一种使用该方法处理逐出的方法:

import { util, Context } from '@aws-appsync/utils'; import { update } from '@aws-appsync/utils/dynamodb'; export function request(ctx) { extensions.evictFromApiCache('Query', 'getNote', { 'ctx.args.id': ctx.args.id }); return update({ key: { id: ctx.args.id }, update: { context: ctx.args.content } }); } export const response = (ctx) => ctx.result;

或者,您也可以在响应处理程序中处理逐出。

在处理 updateNote 变更时,Amazon AppSync 尝试逐出条目。如果成功清除条目,响应将在 extensions 对象中包含一个 apiCacheEntriesDeleted 值,以显示删除的条目数:

"extensions": { "apiCacheEntriesDeleted": 1}

根据身份逐出缓存条目

您可以根据 context 对象中的多个值创建缓存键。

例如,采用以下架构,该架构将 Amazon Cognito 用户池作为默认身份验证模式并由 Amazon DynamoDB 数据来源提供支持:

type Note { id: ID! # a slug; e.g.: "my-first-note-on-graphql" title: String content: String! } type Query { getNote(id: ID!): Note } type Mutation { updateNote(id: ID!, content: String!): Note }

Note 对象类型保存在 DynamoDB 表中。该表具有一个组合键,该组合键将 Amazon Cognito 用户名作为主键,并将 Noteid(短标签)作为分区键。这是一个多租户系统,允许多个用户托管和更新他们的私有 Note 对象,这些对象从不进行共享。

由于这是一个读取密集型系统,因此,getNote 查询使用每个解析器的缓存进行缓存,缓存键由 [context.identity.username, context.arguments.id] 组成。在更新 Note 后,您可以逐出该特定 Note 的条目。您必须按照解析器的 cachingKeys 列表中指定的相同顺序将组件添加到对象中。

以下示例说明了这一点:

import { util, Context } from '@aws-appsync/utils'; import { update } from '@aws-appsync/utils/dynamodb'; export function request(ctx) { extensions.evictFromApiCache('Query', 'getNote', { 'ctx.identity.username': ctx.identity.username, 'ctx.args.id': ctx.args.id, }); return update({ key: { id: ctx.args.id }, update: { context: ctx.args.content } }); } export const response = (ctx) => ctx.result;

后端系统也可以更新 Note 并逐出条目。例如,采用以下变更:

type Mutation { updateNoteFromBackend(id: ID!, content: String!, username: ID!): Note @aws_iam }

您可以逐出条目,但将缓存键的组件添加到 cachingKeys 对象中。

在以下示例中,逐出是在解析器响应中进行的:

import { util, Context } from '@aws-appsync/utils'; import { update } from '@aws-appsync/utils/dynamodb'; export function request(ctx) { return update({ key: { id: ctx.args.id }, update: { context: ctx.args.content } }); } export function response(ctx) { extensions.evictFromApiCache('Query', 'getNote', { 'ctx.identity.username': ctx.args.username, 'ctx.args.id': ctx.args.id, }); return ctx.result; }

如果已在 Amazon AppSync 外部更新您的后端数据,您可以调用使用 NONE 数据来源的变量以从缓存中逐出项目。

压缩 API 响应

Amazon AppSync 允许客户端请求压缩的负载。如果请求,将压缩并返回 API 响应,以响应指示希望压缩内容的请求。压缩的 API 响应加载速度更快,内容下载速度更快,并且您的数据传输费用也可能会下降。

注意

压缩适用于在 2020 年 6 月 1 日之后创建的所有新 API。

Amazon AppSync 尽力压缩对象。在极少数情况下,Amazon AppSync 可能会根据多种因素(包括当前容量)跳过压缩。

Amazon AppSync 可以将 GraphQL 查询负载大小压缩到 1,000 到 10,000,000 字节之间。要启用压缩,客户端必须发送具有 gzip 值的 Accept-Encoding 标头。可以检查响应 (gzip) 中的 Content-Encoding 标头值以验证压缩。

默认情况下,Amazon AppSync 控制台中的查询浏览器自动设置请求中的标头值。如果您执行的查询具有足够大的响应,可以使用浏览器开发人员工具确认压缩。