缓存概览

可缓存响应是一种可供 Cloud CDN 存储并快速检索,因而有助于缩短加载时间的 HTTP 响应。并非所有 HTTP 响应都可以缓存。

可缓存的内容

Cloud CDN 只会缓存那些满足本部分所列全部要求的响应。其中一些要求是 RFC 7234 中规定的,而其他要求则专门针对 Cloud CDN。

只有满足以下全部条件时,响应才能存储在 Cloud CDN 缓存中:

特性 要求
来源 已启用 Cloud CDN 的后端服务、后端存储分区或自定义源站
所响应的请求 GET 请求
状态代码 200203206300301302307410
缓存指令 具有带 public 指令的 Cache-Control 标头
新鲜度 具有带 max-ages-maxage 指令的 Cache-Control 标头,或者具有带未来时间戳的 Expires 标头
内容

包含有效的 Content-LengthContent-RangeTransfer-Encoding 标头

例如,与响应大小完全匹配的 Content-Length 标头

大小 大小不超过大小上限

对于 Cloud Storage 后端存储分区,您可以通过以下几种方式来满足这些要求:

  • 将您的存储分区设为可公开读取。 我们建议使用这种方法来公开内容。如此设置时,互联网上的任何人都可以查看和列出您的对象及其元数据(不包括 ACL)。建议的做法是为公开对象使用专用的存储分区。如需了解详情,请参阅建议的存储分区架构

  • 将单个对象设为可公开读取。 我们不建议采用这种方法。

默认情况下,如果整个存储分区是公开的,或者个别对象是公开的,并且个别对象并未指定 Cache-Control 元数据,则 Cloud Storage 会为这些对象分配 Cache-Control: public, max-age=3600 标头。您可以使用 Cache-Control 元数据设置不同的值。

如需查看显示如何使用后端存储分区配置外部 HTTP(S) 负载平衡器的示例,请参阅使用后端存储分区设置 Cloud CDN

大小上限

Cloud CDN 会对每个响应强制执行大小上限。正文超出大小上限的任何响应都不会被缓存,但仍会传送给客户端。

大小上限的值取决于源站服务器是否支持字节范围请求

源站服务器支持字节范围请求 源站服务器不支持字节范围请求
5 TB(5497558138880 字节) 10 MB(10485760 字节)

几乎所有现代 Web 服务器(包括 NGINX、Apache 和 Varnish)都支持字节范围请求。

无法缓存的内容

某些检查会禁止系统对响应进行缓存。

如果一条响应不符合可缓存的内容的要求,或者满足下述任一条件,则该响应不会被缓存。

特性 要求
来源 未启用 Cloud CDN 的后端服务、后端存储分区或自定义源站
Cookie 具有 Set-Cookie 标头
响应指令 具有带 no-storeno-cacheprivate 指令的 Cache-Control 标头
请求指令 请求具有 Cache-Control: no-store 标头
大小 超过大小上限

未来这些要求可能会放宽,从而允许 Cloud CDN 缓存更多响应。

如果存在 Cache-Control: no-storeno-cacheprivate,但内容仍然被缓存,这说明系统配置了网址签名。下一部分介绍了如何防止对响应进行缓存。

防止缓存

要防止不公开信息缓存在 Cloud CDN 缓存中,请执行以下操作:

  1. 对于不应在 Cloud CDN 缓存中存储的响应,在响应中包含 Cache-Control: private 标头;对于不应在任何缓存(即便是网络浏览器缓存)中存储的响应,在响应中包含 Cache-Control: no-store 标头。
  2. 不要对可访问不公开信息的网址签名。使用签名网址访问内容时,响应中无论是否有任何 Cache-Control 指令,都有可能被缓存。

缓存键

Cloud CDN 缓存中的每个缓存条目都通过缓存键来标识。当请求进入缓存时,缓存会将请求的 URI 转换为缓存键,然后将该键与缓存条目的键进行比较。如果找到匹配的键,缓存将返回与该键关联的对象。

对于后端服务,Cloud CDN 默认使用完整请求 URI 作为缓存键。例如,https://example.com/images/cat.jpgcat.jpg 对象的特定请求的完整 URI。该字符串用作默认缓存键。只有 URI 与该字符串完全相同的请求才视为匹配。URI 为 http://example.com/images/cat.jpghttps://example.com/images/cat.jpg?user=user1 的请求不匹配。

您可以更改将 URI 中的哪些部分用在缓存键中。文件名和路径必须始终作为缓存键的一部分,不过您还可以在自定义缓存键时包含或省略协议、主机或查询字符串中的任意一项或多项。 使用缓存键介绍了如何自定义缓存键。

URI 部分 自定义 具有相同缓存键的网址示例
协议 在缓存键中省略协议。
  • https://example.com/images/cat.jpg
  • http://example.com/images/cat.jpg
主机 在缓存键中省略主机。
  • https://example.com/images/cat.jpg
  • https://example2.com/images/cat.jpg
查询字符串

在缓存键中省略查询字符串。

选择性地省略或包含查询字符串的各部分。

  • https://example.com/images/cat.jpg?user=user1
  • https://example.com/images/cat.jpg?user=user2

除了包含或省略整个查询字符串之外,您还可以借助包含列表和排除列表来使用查询字符串的各个部分。

对于后端存储分区,缓存键由不带协议、主机或查询字符串的 URI 组成。

因此,对于给定后端存储分区,以下 URI 会解析为相同的缓存对象:

  • http://example.com/images/cat.jpg
  • https://example.com/images/cat.jpg
  • https://example.com/images/cat.jpg?user=user1
  • http://example.com/images/cat.jpg?user=user1
  • https://example.com/images/cat.jpg?user=user2
  • https://media.example.com/images/cat.jpg
  • https://www.example.com/images/cat.jpg

查询字符串包含列表

您可以选择性地控制 Cloud CDN 在缓存键中包含哪些查询字符串参数。例如,如果您创建了 user 的包含列表,则 https://example.com/images/cat.jpg?user=user1&color=blue 会创建 https://example.com/images/cat.jpg?user=user1 缓存键,该键也与 https://example.com/images/cat.jpg?user=user1&color=red 匹配。

要使用此选项,您必须添加查询字符串、指定非空的包含列表,并且不指定排除列表。

查询字符串排除列表

您可以使用排除列表选择性地控制 Cloud CDN 忽略哪些查询字符串参数。例如,如果您创建了一个 user 排除列表,则缓存键中将使用除 user 之外的所有查询字符串参数

在配置上述排除列表并输入 https://example.com/images/cat.jpg?user=user1&color=blue 之后,Cloud CDN 会创建 https://example.com/images/cat.jpg?color=blue 缓存键,该缓存键也与 https://example.com/images/cat.jpg?user=user2&color=blue 匹配,但与 https://example.com/images/cat.jpg?user=user1&color=red 不匹配。

要使用此选项,您必须添加查询字符串、指定非空的排除列表,并且不指定包含列表。

Vary 标头

除了请求 URI 之外,Cloud CDN 还会遵循源站服务器在响应中包含的任何 Vary 标头。Vary 标头表明响应会因客户端的请求标头而异。例如,如果响应指定了 Vary: Accept,Cloud CDN 会将一个缓存条目用于指定 Accept: image/webp,image/*,*/*;q=0.8 的请求,将另一个缓存条目用于指定 Accept: */* 的请求。

在传送压缩内容时,有时会使用 Vary 标头。Cloud CDN 本身不会对响应进行压缩或解压缩,但它可以传送由源站服务器压缩的响应。如果您的源站服务器根据 Accept-Encoding 请求标头的值来选择是传送压缩内容还是未压缩内容,请确保响应指定 Vary: Accept-Encoding

仅当 Vary 标头包含可缓存的内容中列出的某个值时,系统才会缓存具有该标头的响应。

过期时间和验证请求

Cloud CDN 缓存中的每个缓存条目都有一个到期时间,由 Cache-Control: s-maxageCache-Control: max-age 和/或 Expires 标头根据 RFC 7234 定义。如果存在多个标头,则 Cache-Control: s-maxage 优先于 Cache-Control: max-ageCache-Control: max-age 优先于 Expires

Cloud CDN 收到请求时,它会查询相应的缓存条目并检查该条目的存在时间。如果缓存条目存在并且新鲜度足以满足要求,则可以从缓存中传送响应。但是,如果当前时间晚于过期时间,Cloud CDN 就无法在未事先联系您的某个后端的情况下传送响应。

Cloud CDN 会对存在时间超过 30 天的缓存对象执行重新验证。 这样可以使用户生成的过时缓存内容自动失效并被逐出。当 max-ages-maxage 值超过 30 天(2592000 秒)时,Cloud CDN 会将该值视为 2592000 秒。不过即使 max-ages- maxage 超过 30 天,下游客户端仍会看到其准确值。

如果之前缓存的响应具有 Last-Modified 和/或 ETag 标头,则 Cloud CDN 可以尝试使用这些标头中的信息来向后端验证缓存条目。Cloud CDN 执行此验证的方式略有不同,具体取决于响应是否使用字节范围请求进行缓存:

  • 如果响应是使用使用字节范围缓存的,Cloud CDN 会启动包含 If-Modified-Since 和/或 If-None-Match 标头的单独验证请求。
  • 否则,Cloud CDN 会向客户端请求添加 If-Modified-Since 和/或 If-None-Match 标头,并将修改后的请求转发给后端。

如果缓存的副本仍然是最新的,则后端可以通过发送 304 Not Modified 响应来验证现有缓存条目。在这种情况下,后端只发送响应标头,而不发送响应正文。Cloud CDN 将新的响应标头插入缓存,更新过期时间,并将新的响应标头和缓存的响应正文传送到客户端。

如果之前缓存的响应既没有 Last-Modified 标头,也没有 ETag 标头,则 Cloud CDN 会忽略过期的缓存条目,并将客户端请求不加修改地转发给后端。

缓存条目的过期时间实际上就是一个上限值,它决定了缓存条目保持有效的时长。但在缓存条目过期之前,无法保证其是否始终保留在缓存中。您可以逐出非热门内容的缓存条目,以便为新内容腾出空间。无论指定的过期时间是多久,系统都将自动移除 30 天内未被访问过的缓存条目。

如需了解详情,请参阅驱逐和到期

为字节范围请求提供的支持

如果响应满足以下条件,则表明源站服务器支持字节范围请求:

  • 状态代码:200 OK206 Partial Content
  • 标头:Accept-Ranges: bytes
  • 标头:Content-Length 和/或 Content-Range
  • 标头:带有强验证符的 ETag
  • 标头:Last-Modified

Cloud Storage 支持大多数对象的字节范围请求。但是,除非客户端请求包含 Accept- Encoding: gzip 标头,否则 Cloud Storage 不支持具有 Content-Encoding: gzip 元数据的对象的字节范围请求。如果您的 Cloud Storage 对象大于 10 MB,请确保它们不具有 Content-Encoding: gzip 元数据。如需了解如何修改对象元数据,请参阅查看和修改对象元数据

常见的 Web 服务器软件也支持字节范围请求。如需详细了解如何启用相应支持,请参阅 Web 服务器软件的文档。如需详细了解字节范围请求,请参阅 HTTP 规范

在源站服务器支持字节范围请求的情况下,当 Cloud CDN 缓存第一次收到一条本应可缓存的响应时,如果该响应符合以下任一条件,Cloud CDN 缓存就会拒绝存储该响应:

  • 响应正文不完整,因为客户端只请求了部分内容。
  • 响应正文大于 1 MB(1048576 字节)。

如果发生这种情况,并且响应在其他情况下可以满足正常的可缓存性要求,缓存会记录源站服务器支持该缓存键的字节范围请求,并将源站服务器的响应转发给客户端。

在缓存未命中时,缓存会检查是否已经确知源站服务器支持字节范围请求。如果已经确知源站服务器支持该缓存键的字节范围请求,则缓存不会将客户端请求转发到外部 HTTP(S) 负载平衡器。 在这种情况下,缓存会针对内容的缺失部分发起自己的字节范围缓存填充请求。如果您的源站服务器在 206 Partial Content 响应中返回请求的字节范围,则缓存可以存储该范围,将其用于未来的请求。

只有当收到的 206 Partial Content 响应是对缓存发起的字节范围请求作出的响应时,缓存才会存储该响应。除非先前有记录表明,源站服务器支持相应缓存键的字节范围请求,否则缓存不会发起字节范围请求,因此,对于大于 1 MB 的内容,只有在该内容被第二次访问时,给定的缓存才会存储该内容。

Cloud CDN 发起的请求

当您的源服务器支持字节范围请求时,Cloud CDN 可将多个请求发送到您的源站服务器,以响应单个客户端请求。Cloud CDN 可以发起两种类型的请求:验证请求和字节范围请求。

如果某个响应表明您的源站服务器支持特定缓存键的字节范围请求,且该响应已过期,则 Cloud CDN 会发起验证请求以确认内容未被更改,并且您的源站服务器仍然支持该内容的范围请求。如果您的源站服务器用 304 Not Modified 作为响应,Cloud CDN 会继续使用字节范围来传送内容。否则,Cloud CDN 会将源站服务器的响应转发到客户端。您可以使用 Cache-Control 和 Expires 响应标头控制过期时间。

在缓存未命中时,Cloud CDN 会为与客户端请求重叠的一组字节范围发起缓存填充请求。如果客户端所请求内容的某些范围出现在缓存中,则 Cloud CDN 将从缓存传送尽可能多的内容,并且仅将对于缺失范围的字节范围请求发送到您的源站服务器。

Cloud CDN 发起的每个字节范围请求都指定了一个范围,该范围在开始时设置了一个偏移量(2097136 字节的倍数)。每个范围的大小都同样为 2097136 字节,唯一有可能例外的就是最后一个范围。如果内容的大小不能被 2097136 整除,那么最后一个范围会略小一些。字节范围请求中使用的大小和偏移量将来可能会发生变化。

例如,假设存在一个客户端请求,所请求的是未出现在缓存中的内容的第 1000000 个字节至第 3999999 个字节。在此示例中,Cloud CDN 会发起两个 GET 请求,一个用于获取内容的第一部分(2097136 字节),另一个用于获取第二部分(2097136 字节)。这会导致 4194272 字节的缓存填充 - 尽管客户端只请求了 3000000 字节的内容。

当您使用 Cloud Storage 存储分区作为源站时,我们会将每个 GET 请求视为一项单独的 B 类操作进行计费。您需要为 Cloud Storage 处理的所有 GET 请求付费,其中包括由 Cloud CDN 发起的所有请求。当响应完全由 Cloud CDN 缓存传送时,不会向 Cloud Storage 发送任何 GET 请求,也不会向您收取任何 Cloud Storage 操作的费用。

当 Cloud CDN 发起验证请求或字节范围请求时,它并不会包含特定于客户端的标头,比如 CookieUser-Agent

后续步骤