缓存概览

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

缓存模式

使用缓存模式,您可以控制用于确定 Cloud CDN 是否缓存内容的因素。

Cloud CDN 提供三种缓存模式,其中定义了响应的缓存方式、Cloud CDN 是否遵循源站发送的缓存指令,以及缓存 TTL 的应用方式。

下表显示了可用的缓存模式:

缓存模式 行为
CACHE_ALL_STATIC 自动缓存包含不是不可缓存的静态内容的成功响应。设置有效缓存指令的源站响应也会进行缓存。

对于使用 Google Cloud CLI 或 REST API 创建的已启用 Cloud CDN 的后端,这是默认行为。

USE_ORIGIN_HEADERS 要求成功的源站响应设置有效的缓存指令和有效的缓存标头。没有这些指令的成功响应会从源站转发。
FORCE_CACHE_ALL 无条件缓存成功响应,并跳过源站设置的任何缓存指令。如果后端为每个用户的专用内容(例如动态 HTML 或 API 响应)提供服务,则此模式不适用。

即使缺少有效的缓存指令,错误响应也可能缓存

在将缓存模式设置为 FORCE_CACHE_ALL 之前,请考虑以下行为:

  • 对于签名网址或签名 CookieFORCE_CACHE_ALL 会替换通过 Google Cloud 控制台中的缓存条目最长存在时间设置或 gcloud --signed-url-cache-max-age 选项指定的最长存在时间。

  • FORCE_CACHE_ALL 会更改任何先前缓存内容的存留时间 (TTL)。此更改可能会导致某些之前被视为新鲜的条目(由于源标头中的 TTL 较长)被视为过时,并可能导致某些之前被视为过时的条目被视为新鲜。

  • FORCE_CACHE_ALL 会替换缓存指令(Cache-ControlExpires),但不会替换其他源响应标头。特别是,即使 Vary 标头存在,FORCE_CACHE_ALL 标头仍然会应用,并且可能会禁止缓存。如需了解详情,请参阅 Vary 标头

如需设置说明,请参阅设置缓存模式

静态内容

静态内容是始终相同的内容,即使由不同的用户访问这些内容也是如此。用于给网站设置样式的CSS 以及用于提供交互性、视频和图片内容的 JavaScript,通常不会针对每个用户更改给定网址(缓存键),因此可以从 Cloud CDN 的全球边缘网络缓存受益。

如果您将缓存模式设置为 CACHE_ALL_STATIC,并且响应在 Cache-ControlExpires 标头中没有显式缓存指令,则 Cloud CDN 会自动缓存以下内容的该响应:

  • Web 资源,包括 CSS (text/css)、JavaScript (application/javascript) 以及包括 WOFF2 (font/woff2) 在内的所有 Web 字体
  • 图片,包括 JPEG (image/jpg) 和 PNG (image/png)
  • 视频,包括 H.264、H.265 和 MP4 (video/mp4),以及音频文件,包括 MP3 (audio/mpeg) 和 MP4 (audio/mp4)
  • 格式化文档,包括 PDF 文件 (application/pdf)

下表进行了总结。

类别 MIME 类型
Web 资源 text/css text/ecmascript text/javascript application/javascript
字体 font/* 相匹配的所有 Content-Type
图片 image/* 相匹配的所有 Content-Type
视频 video/* 相匹配的所有 Content-Type
音频 audio/* 相匹配的所有 Content-Type
格式化文档类型 application/pdfapplication/postscript

Cloud CDN 检查 Content-Type HTTP 响应标头,该标头反映所传送内容的 MIME 类型

注意事项:

  • 您的源站 Web 服务器软件必须为每个响应设置 Content-Type。许多 Web 服务器会自动设置 Content-Type 标头,包括 NGINX、Varnish 和 Apache。

  • 使用 Google Cloud 控制台或 gsutil 工具上传内容时,Cloud Storage 会在上传时自动设置 Content-Type 标头。

  • 如果响应可根据其 MIME 类型缓存,但 Cache-Control 响应标头为 privateno-store,或标头为 Set-Cookie查看规则的完整列表),则不会缓存该响应。

Cloud CDN 不会使用网址路径中的文件扩展名来确定响应是否可缓存,因为很多有效的可缓存响应没有反映在网址中。

如果您要缓存 text/htmlapplication/json 内容类型,则必须在响应中设置显式 Cache-Control 标头,以避免意外缓存某个用户的数据,并将其传送给所有用户。

可缓存的内容

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

Cloud CDN 可能会定期更改其用于缓存内容的具体条件集。如果要明确阻止 Cloud CDN 缓存您的内容,请遵循 RFC 7234 中的准则,以确定如何指定保证不可缓存的响应。另请参阅基于源标头的不可缓存内容部分。

如果满足以下所有条件,则 Cloud CDN 会将响应存储在缓存中:

属性 要求
来源 已启用 Cloud CDN 的后端服务、后端存储桶或外部后端
所响应的请求 GET 请求
状态代码

200203204206300301302307308404405410421451501

时效性

响应具有含 max-ages-maxage 指令的 Cache-Control 标头,或者具有带未来时间戳的 Expires 标头。

对于没有存在时间的可缓存响应(例如具有 no-cache),必须明确提供 public 指令。

CACHE_ALL_STATIC 缓存模式下,如果不存在新鲜度指令,则包含静态内容类型的成功响应仍可缓存。

FORCE_CACHE_ALL 缓存模式下,任何成功的响应都有资格缓存。这可能导致缓存特定于每位用户的(可识别用户个人身份信息的)非公开内容。您应仅在不会提供非公开内容或动态内容的后端(比如 Cloud Storage 存储桶)中设置 FORCE_CACHE_ALL

如果启用了负缓存并且状态代码与负缓存指定 TTL 的状态代码匹配,则即使没有显式新鲜度指令,响应也有资格进行缓存。

内容

对于 HTTP/1 来源,响应必须包含有效的 Content-LengthContent-RangeTransfer-Encoding: chunked 标头。

对于使用更高级 HTTP 协议版本(HTTP/2 及更高版本)的来源,响应无需具有此类标头。

大小 大小不超过大小上限

对于大小介于 10 MB 到 100 GB 之间的响应,请参阅字节范围请求中所述的其他可缓存性限制。

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

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

  • 使用托管文件夹将存储桶的一部分设为可公开读取。

  • 将单个对象设为可公开读取。 我们不建议使用此方法,因为它使用旧版 Cloud Storage 专用的权限系统。

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

如需查看显示如何使用后端存储桶配置外部应用负载均衡器的示例,请参阅使用后端存储桶设置 Cloud CDN

大小上限

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

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

源站服务器支持字节范围请求 源站服务器不支持字节范围请求
100 GB(107,374,182,400 字节) 10 MB(10,485,760 字节)

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

基于源标头的不可缓存内容

某些检查会禁止系统对响应进行缓存。 Cloud CDN 可能会定期更改其用于缓存内容的具体条件集,因此,如果要明确阻止 Cloud CDN 缓存您的内容,请遵循标准 (RFC 7234) 中的准则,以确定如何指定保证不可缓存的响应。

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

属性 要求
来源 未启用 Cloud CDN 的后端服务或外部后端
Cookie 具有 Set-Cookie 标头
Vary 标头 值不是 AcceptAccept-EncodingAccess-Control-Request-HeadersAccess-Control-Request-MethodOriginSec-Fetch-DestSec-Fetch-ModeSec-Fetch-SiteX-Goog-Allowed-ResourcesX-Origin,或者配置为缓存键设置的一部分的标头之一。
响应指令 响应具有含 no-storeprivate 指令的 Cache-Control 标头(除非使用 FORCE_CACHE_ALL 缓存模式,在该模式下,Cache-Control 标头会被忽略)
请求指令 请求包含 Cache-Control: no-store 指令
请求授权 请求具有 Authorization 标头,除非被响应 Cache-Control 替换
大小 超过大小上限

如果存在 Cache-Control: no-storeprivate,但内容仍在缓存中,则可能是由下列某种原因造成的:

  • 已配置网址签名。
  • 将 Cloud CDN 缓存模式设置为强制缓存所有响应。

防止缓存

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

  1. 确保 Cloud CDN 缓存模式未设置为 FORCE_CACHE_ALL 模式,此模式会无条件缓存所有成功响应。
  2. 对于不应在 Cloud CDN 缓存中存储的响应,在响应中包含 Cache-Control: private 标头;对于不应在任何缓存(即便是网络浏览器缓存)中存储的响应,在响应中包含 Cache-Control: no-store 标头。
  3. 签署可访问不公开信息的网址。使用签名网址访问内容时,响应中无论是否有任何 Cache-Control 指令,都有可能被缓存。
  4. 当缓存模式设置为 USE_ORIGIN_HEADERSCACHE_ALL_STATIC 时,对于包含 Authorization 请求标头的源站(缓存填充)请求,Cloud CDN 只会缓存包含 publicmust-revalidates-maxage 缓存控制指令的响应。这可以防止意外缓存每个用户的内容和/或需要进行身份验证的内容。FORCE_CACHE_ALL 缓存模式没有此限制。

添加自定义响应标头

借助自定义响应标头,您可以指定经典版应用负载均衡器添加到代理响应中的标头。借助自定义响应标头,您可以反映客户端、客户端地理数据和您自己的静态响应标头的缓存状态。

如需查看标头列表,请参阅可以出现在标头值中的变量

如需说明,请参阅使用自定义响应标头

全球外部应用负载均衡器上的 Cloud CDN 部署不支持自定义响应标头。

缓存键

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 组成。默认情况下,只有 Cloud Storage 已知的查询参数会作为缓存键的一部分包含在内(例如“generation”)。

因此,对于给定后端存储桶,以下 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

您可以更改将 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

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

查询字符串包含列表

您可以选择性地控制 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 Storage 缓存键的查询字符串包含列表

在 Cloud Storage 存储桶的缓存键中包含网址查询参数有助于支持缓存无效化。缓存无效化是一种允许用户查找已上传文件的新版本的过程,即使在旧版本仍通过 TTL 有效缓存的情况下也是如此。

在用于从后端存储桶传送响应的缓存键中,您可以通过包含列表包含特定查询参数。虽然 Cloud Storage 不会根据查询参数提供不同的内容或路由,但您可选择包含参数,以缓存 Cloud Storage 存储桶中存储的静态内容。

例如,您可以附加基于底层内容的 ?version=VERSION?hash=HASH 查询参数。这限制了需要主动使内容失效的需要,并且符合现代 Web 开发工作流,在这种工作流中,Web 框架和网址使用内容的哈希值来避免跨部署传送过时的对象。

由于仅通过选择接受的方式在缓存键中包含查询参数,因此 Cloud CDN 不支持将缓存键中的查询参数排除到后端存储桶中。

查询字符串排除列表

您可以使用排除列表选择性地控制 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 不匹配。

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

查询参数顺序

生成的缓存键不依赖于查询参数的顺序。

例如,以下查询参数将生成相同的缓存键:

  • info=123&variant=13e&geography=US
  • geography=US&variant=13e&info=123

HTTP 标头和 HTTP Cookie 缓存键设置

您可以使用以下缓存键配置设置,以提高缓存命中率和源站分流。

  • 对于后端服务和存储桶:通过在缓存键配置中包含命名标头,将 HTTP 标头用作缓存键的一部分。
  • 仅适用于后端服务:将命名的 HTTP Cookie 用作缓存键,例如 A/B(多变量)测试、Canary 版本等类似情景。

在请求中包含额外的 HTTP 标头或 HTTP Cookie 的缓存请求会缓存到该缓存键的缓存位置的第三个请求中。这样可以降低高基数标头/Cookie 值对于缓存逐出率的影响。在正常情况下和用户流量条件下,这种影响应该不甚明显,热门内容仍会保持缓存状态。

包含请求标头

如需对响应的其他变体进行缓存,您可以在缓存键中包含额外的请求标头。

某些键不允许在缓存键中使用,因为它们的基数往往很高。大多数情况下,这些标头的值或者对于各用户是唯一的 (Cookie,Authorization),或者具有数千个可能的值 (Referer, User-Agent, Accept)。例如,考虑到多种多样的浏览器、用户设备和操作系统,User-Agent 标头可能有 5000 多个唯一值。这些类型的标头会对缓存命中率产生严重的负面影响。

仅可接受根据 RFC 7230 有效的 HTTP 标头字段名称。 标头字段名称不区分大小写,并且重复项会被拒绝。

您可以选择将源站服务器配置为在 Vary 响应中包含已配置的缓存键请求标头。这对于 Cloud CDN 而言不是必需的,但对于下游缓存很有用。如需了解详情,请参阅 Vary 标头

Cloud CDN 不允许在标头列表中包含以下标头:

  • Accept
  • Accept-Encoding
  • Authority,因为此设置由配置 (cdnPolicy.includeHost) 进行控制
  • Authorization,通常针对每位用户,例如在 OAuth Bearer 令牌中
  • CDN-Loop
  • Connection
  • Content-MD5
  • Content-Type
  • Cookie
  • Date
  • Forwarded,通常针对各客户端或各代理
  • From
  • Host,因为此设置由配置 (cdnPolicy.includeHost) 进行控制
  • If-MatchIf-Modified-SinceIf-None-Match
  • Origin
  • Proxy-Authorization
  • Range
  • Referer(或Referrer
  • User-Agent
  • Want-Digest
  • Django 和 Ruby on Rails 使用的 X-CSRFTokenX-CSRF-Token
  • X-Forwarded-For,通常针对各客户端或各代理
  • X-User-IP
  • 使用如下内容开头的任何标头:
    • Access-Control-,例如 Access-Control-Request-HeadersAccess-Control-Request-Method
    • Sec-Fetch-
    • Sec-GFE-
    • Sec-Google-
    • X-Amz-
    • X-GFE-
    • X-Goog-
    • X-Google-

具有不同值的相同标头

假设用户发送了具有不同标头值的多个同名标头,例如:

My-Header: Value1
My-Header: Value2

在这种情况下,Cloud CDN 会修改标头,它会假设标头必须遵循允许某些标头具有多个值的标准惯例。Cloud CDN 将它们合并到英文逗号分隔列表中并发送到后端,就像客户端发送了以下内容:

My-Header: Value1, Value2

包含命名 Cookie

HTTP Cookie 是一种 name=value 配对,而一个请求可以包含多个 HTTP Cookie,它们可以列在同一行中并由英文分号分隔,也可以作为独立的 Cookie 请求标头,每个标头对应一个 Cookie。

您最多可以提供一个包含五个 Cookie 名称的列表。

用户代理(例如网络浏览器)通常会将每个网域存储的 Cookie 数量限制为 4 KB;确保不要发送过多(或过大)的 Cookie,因为用户代理可能不会发送请求中的所有 Cookie。这可能会影响用户是否会收到特定的缓存响应。

如果您要从与发出 Cookie 所用的主机名不同的其他主机名传送静态内容,请确保 Cookie 的 Domain 特性(和 Path)特性允许同时发送 Cookie。

如果请求包含同一 Cookie 名称的多个实例,则系统只会接受第一个实例。

缓存控制指令

HTTP 缓存控制指令会影响 Cloud CDN 的行为,如下表所示。

N/A 表示指令不适用于请求或响应。

指令 请求 响应
no-store 如果请求中存在该指令,则 Cloud CDN 将采用该指令且不将响应存储在缓存中。

系统不会缓存具有 no-store 的响应。

您可以根据后端将此设置替换为 FORCE_CACHE_ALL 缓存模式。

no-cache 系统会忽略 no-cache 请求指令,以防止客户端可能向来源发起或强制重新验证。

系统会缓存具有 no-cache 的响应,但必须在传送前使用来源重新验证该响应。

您可以根据后端将此设置替换为 FORCE_CACHE_ALL 缓存模式。

public 不适用

此指令不是可缓存性所必需的,但最佳做法是将它包含在应由代理缓存的内容中。

private 不适用

具有 private 指令的响应不会被 Cloud CDN 缓存,即使该响应被视为可缓存也是如此。客户端(如浏览器)可能仍会缓存结果。

您可以根据后端将此设置替换为 FORCE_CACHE_ALL 缓存模式。 使用 no-store 可阻止响应的所有缓存。

max-age=SECONDS 系统会忽略 max-age 请求指令。返回缓存的响应就像此标头未包含在请求中一样。 具有 max-age 指令的响应缓存时间长达定义的 SECONDS
s-maxage=SECONDS 不适用

具有 s-maxage 指令的响应缓存时间长达定义的 SECONDS

如果同时存在 max-ages-maxage,则 Cloud CDN 会使用 s‑maxage

具有此指令的响应不会过时传送。

s-max-age(两个连字符)对缓存无效。

min-fresh=SECONDS 系统会忽略 min-fresh 请求指令。返回缓存的响应就像此标头未包含在请求中一样。 不适用
max-stale=SECONDS

max-stale 请求指令指示客户端愿意接受的过时上限(以秒为单位)。

Cloud CDN 会采用此指令,并且仅在响应过时小于 max-stale 指令时才会返回过时缓存的响应。否则,Cloud CDN 会在处理请求前进行重新验证。

不适用
stale-while-revalidate=SECONDS 不适用

具有 stale-while-revalidate 的响应传送至客户端的时间长达 SECONDS,同时异步执行重新验证。

您可以通过对后端设置 cdnPolicy.serveWhileStale 为所有响应启用此行为。

stale-if-error=SECONDS 系统会忽略 stale-if-error 请求指令。返回缓存的响应就像此标头未包含在请求中一样。

此响应标头没有任何影响。

must-revalidate 不适用

具有 must-revalidate 的响应会在到期后使用源服务器进行重新验证。

具有此指令的响应不会过时传送。

proxy-revalidate

具有 proxy-revalidate 的响应会在到期后使用源服务器进行重新验证。

具有此指令的响应不会过时传送。

immutable 不适用 无影响。此响应会传递给客户端。
no-transform 不适用 Cloud CDN 不会应用任何转换。
only-if-cached 系统会忽略 only-if-cached 请求指令。返回缓存的响应就像此标头未包含在请求中一样。 不适用

Cloud CDN 尽可能符合 RFC 规范 (HTTP RFC 7234),但更倾向于优化缓存分流,并最大限度地降低客户端对命中率和/或总体来源负载的影响。

对于使用 HTTP/1.1 Expires 标头的响应:

  • Expires 标头的值必须是 RFC 7231 中定义的有效 HTTP 日期。
  • 过去的日期值、无效日期或值 0 表示内容已过期,需要重新验证。
  • 如果响应中存在 Cache-Control 标头,则 Cloud CDN 会忽略 Expires 标头。

如果响应中存在有效的未来 Expires 标头,则可缓存响应且无需指定其他缓存指令。

如果响应中存在 HTTP/1.0 Pragma 标头,则 Cloud CDN 会忽略该标头,并按原样将其传递给客户端。带有此标头的客户端请求会传递给来源,并且不会影响 Cloud CDN 传送响应的方式。

Vary 标头

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

不可缓存的内容部分的表列出了允许缓存内容的 Vary 标头。其他 Vary 标头值会阻止内容被缓存。

FORCE_CACHE_ALL 缓存模式不会覆盖此行为。Vary 标头对于避免多个可能源站服务器响应之间的缓存投毒攻击非常重要。如果 FORCE_CACHE_ALL 导致系统缓存这些响应,则系统会面临危险。

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

在使用缓存键中的 HTTP 标头时,Cloud CDN 会根据指定请求标头的值缓存响应的多个副本,这与 Vary 支持类似,但源站服务器无需明确指定任何 Vary 响应标头。如果源站在 Vary 响应中指定了缓存键标头,则 Cloud CDN 会正确对待响应,就如同 Vary 响应中未提及这些标头一样。

过期时间和验证请求

缓存条目的过期时间定义了缓存条目保持有效的时长。s-maxage(或 max-ageexpires)值提供的值允许自动重新验证用户生成的过时缓存内容。

Cloud CDN 收到请求时,它会查询相应的缓存条目并检查该条目的存在时间。如果缓存条目存在并且新鲜度足以满足要求,则可以从缓存中传送响应。但是,如果当前时间晚于过期时间,Cloud CDN 将尝试通过与您的其中一个后端连接来重新验证缓存条目。此操作在传送响应之前完成,除非您启用了在过时的情况下传送,在这种情况下会异步执行重新验证。

对于某些缓存模式,您可以设置 TTL 值。如需了解详情,请参阅使用 TTL 设置和替换

缓存模式会影响确定新鲜度的方式。

缓存模式 验证行为
CACHE_ALL_STATIC 系统会查询源站标头(Cache-Control: s-maxageCache-Control: max-ageExpires 标头)以确定新鲜度。对于静态内容,如果源站标头不存在,则配置的 default_ttl 会确定新鲜度。静态内容的时间晚于 default_ttl 后,Cloud CDN 会对其进行重新验证。
USE_ORIGIN_HEADERS Cloud CDN 缓存中的每个缓存条目都有一个过期时间,由 Cache-Control: s-maxageCache-Control: max-ageExpires 标头根据 RFC 7234 定义。
FORCE_CACHE_ALL 配置的 default_ttl 将确定新鲜度,而不是源站标头。内容的时间晚于 default_ttl 后,Cloud CDN 会对其进行重新验证。

如果存在多个标头,则 Cache-Control: s-maxage 优先于 Cache-Control: max-ageCache-Control: max-age 优先于 Expires

默认情况下,当过期时间值超过 30 天(2592000 秒)时,Cloud CDN 会将过期时间值视为 2592000 秒。不过即使 max-ages-maxage 超过 30 天,下游客户端仍会看到其准确值。

逐出

我们无法保证缓存条目在过期之前一直保留在缓存中,因为非热门条目可以在随时过期之前被逐出,以便为新内容腾出空间。作为上限,系统会自动逐出 30 天内未被访问的缓存条目。

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

使用条件请求进行验证

Cloud CDN 可以尝试使用缓存的响应标头中的信息来向后端验证缓存条目。如果同时满足以下两个条件,则会出现这种情况:

  • 之前缓存的响应具有 Last-ModifiedETag 标头。
  • 客户端请求是一个不包含 If-Modified-SinceIf-None-Match 标头的 GET 请求。

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 会忽略过期的缓存条目,并将客户端请求不加修改地转发给后端。

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

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

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

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

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

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

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

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

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

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

由于 Cloud CDN 具有分布式特性,因此 Cloud CDN 有时可能会从每个位置多次从源站提取最后一个数据块。这只会影响每个缓存键的前几个请求。

请求折叠(合并)

请求折叠(也称为“合并”)将针对同一缓存键的多个用户发起的缓存填充请求主动折叠为每个边缘节点的一个源站请求。这样可以主动减少源站负载,适用于项请求(直接提取响应)和请求(Cloud CDN 使用 Range 请求更高效地提取较大对象)。

请求折叠默认启用。

折叠的请求的行为方式如下:

  • 折叠的请求会记录面向客户端的请求和(折叠的)缓存填充请求。
  • 折叠会话的标头用于发出源站填充请求。
  • 不属于缓存键的请求特性(例如 User-AgentAccept-Encoding 标头)仅反映折叠会话的标头
  • 无法折叠缓存键不同的请求。

下图展示了请求是如何合并的:

启用了请求折叠的 Cloud CDN。
启用了请求收起功能的 Cloud CDN(点击可放大)。

相比之下,如果停用了请求折叠或者请求无法合并,源站请求和响应的数量可以等于尝试检索当前未缓存对象的客户端的数量。

未启用请求折叠的 Cloud CDN。
未启用请求收起功能的 Cloud CDN(点击可放大)。

对于所有类型的请求,默认情况下会启用折叠。对于项请求类型,您可以停用折叠。我们建议在对延迟时间高度敏感且无需考虑源站负载的场景中(例如广告投放)停用项请求折叠。

下表总结了不同请求类型的默认行为和可配置性。

请求类型 默认行为 可配置 折叠的优势
块请求 已启用 可显著减少源站带宽
项请求 已启用 可减少源站请求量

使用 Google Cloud CLI 为引用 Cloud Storage 存储桶的后端存储桶停用项请求折叠:

gcloud

使用 gcloud compute backend-servicesbackend-buckets 命令:

gcloud compute backend-services update BACKEND_SERVICE_NAME \
    --no-request-coalescing

要使用 Google Cloud CLI 在后端存储桶上启用项请求折叠,请执行以下操作:

gcloud

使用 gcloud compute backend-buckets 命令:

gcloud compute backend-buckets update BACKEND_BUCKET_NAME \
    --request-coalescing

如需使用 Google Cloud CLI 为后端服务(包括虚拟机组和外部后端)启用项请求折叠,请按如下所述操作:

gcloud

使用 gcloud compute backend-services 命令:

gcloud compute backend-services update BACKEND_SERVICE_NAME \
    --request-coalescing

Cloud CDN 发起的请求

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

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

当缓存未命中时,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

在 Cloud Logging httpRequest.userAgent 字段中,Cloud-CDN-Google 表示请求由 Cloud CDN 发起。

绕过缓存

通过缓存绕过,包含特定请求标头的请求可以绕过缓存,即使之前已缓存内容也可以如此。

本部分介绍了如何绕过包含 HTTP 标头(例如 PragmaAuthorization)的缓存。如果您要确保用户或客户始终重新从来源服务器提取最新内容,则此功能非常有用。建议您在测试、设置暂存目录或脚本时执行此操作。

如果指定的标头匹配,则系统会为所有缓存模式设置(即使是 FORCE_CACHE_ALL)绕过缓存。如果指定的标头在许多请求中很常见,则缓存绕过会导致大量缓存未命中。

准备工作

  • 确保已启用 Cloud CDN;如需了解相关说明,请参阅使用 Cloud CDN

  • 如有必要,请更新到 Google Cloud CLI 的最新版本:

    gcloud components update
    

配置缓存绕过

您最多可以指定五个 HTTP 标头名称。值不区分大小写。 标头名称必须是有效的 HTTP 标头字段令牌。标头名称不能在已添加标头的列表中出现多次。 如需了解有效标头名称的规则,请参阅自定义标头的工作原理

控制台

  1. 在 Google Cloud 控制台中,前往负载均衡页面。

    转到“负载均衡”页面

  2. 点击外部应用负载均衡器的名称。
  3. 点击修改
  4. 后端配置中,选择一个后端,然后点击修改
  5. 确保选择启用 Cloud CDN
  6. 在窗口底部,点击高级配置
  7. 绕过请求标头的缓存下,点击添加标头
  8. 输入标头名称,例如 PragmaAuthorization
  9. 点击更新
  10. 再次点击更新

gcloud

对于后端存储桶,请使用带有 --bypass-cache-on-request-headers 标志的 gcloud compute backend-buckets creategcloud compute backend-buckets update 命令。

对于后端服务,请使用带有 --bypass-cache-on-request-headers 标志的 gcloud compute backend-services creategcloud compute backend-services update 命令。

gcloud compute backend-buckets (create | update) BACKEND_BUCKET_NAME
    --bypass-cache-on-request-headers=BYPASS_REQUEST_HEADER
gcloud compute backend-services (create | update) BACKEND_SERVICE_NAME
    --bypass-cache-on-request-headers=BYPASS_REQUEST_HEADER

例如:

gcloud compute backend-services update my-backend-service
    --bypass-cache-on-request-headers=Pragma
    --bypass-cache-on-request-headers=Authorization

api

对于后端存储桶,请使用 方法:backendBuckets.insert方法:backendBuckets.update方法:backendBuckets.patch API 调用。

对于后端服务,请使用方法:backendServices.insert方法:backendServices.update方法:backendServices.patch API 调用。

例如:

PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets

将以下代码段添加到 JSON 请求正文:

"cdnPolicy": {
  "bypassCacheOnRequestHeaders": [
    {
      "headerName": string
    }
  ]
}

停用缓存绕过

gcloud

对于后端存储桶,请使用带有 --no-bypass-cache-on-request-headers 标志的 gcloud compute backend-buckets creategcloud compute backend-buckets update 命令。

对于后端服务,请使用带有 --no-bypass-cache-on-request-headers 标志的 gcloud compute backend-services creategcloud compute backend-services update 命令。

gcloud compute backend-services (create | update) (BACKEND_SERVICE_NAME | BACKEND_BUCKET_NAME)
    --no-bypass-cache-on-request-headers

api

对于后端存储桶,请使用方法:backendBuckets.insert方法:backendBuckets.update API 调用。

对于后端服务,请使用方法:backendServices.insert方法:backendServices.update API 调用。

使用以下 API 调用之一:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets
PUT https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets/BACKEND_BUCKET
POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices
PUT https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/BACKEND_SERVICE

将以下代码段添加到 JSON 请求正文:

"cdnPolicy": {
  "fields": "bypassCacheOnRequestHeaders"
}

后续步骤