可缓存响应是一种可供 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
之前,请考虑以下行为:
对于签名网址或签名 Cookie,
FORCE_CACHE_ALL
会替换通过 Google Cloud 控制台中的缓存条目最长存在时间设置或gcloud --signed-url-cache-max-age
选项指定的最长存在时间。FORCE_CACHE_ALL
会更改任何先前缓存内容的存留时间 (TTL)。此更改可能会导致某些之前被视为新鲜的条目(由于源标头中的 TTL 较长)被视为过时,并可能导致某些之前被视为过时的条目被视为新鲜。FORCE_CACHE_ALL
会替换缓存指令(Cache-Control
和Expires
),但不会替换其他源响应标头。特别是,即使缓存模式为FORCE_CACHE_ALL
,Vary
标头也可能会禁止缓存。如需了解详情,请参阅 Vary 标头。
如需设置说明,请参阅设置缓存模式。
静态内容
静态内容是始终相同的内容,即使由不同的用户访问这些内容也是如此。用于给网站设置样式的CSS 以及用于提供交互性、视频和图片内容的 JavaScript,通常不会针对每个用户更改给定网址(缓存键),因此可以从 Cloud CDN 的全球边缘网络缓存受益。
如果您将缓存模式设置为 CACHE_ALL_STATIC
,并且响应在 Cache-Control
或 Expires
标头中没有显式缓存指令,则 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/pdf 和 application/postscript |
Cloud CDN 检查 Content-Type
HTTP 响应标头,该标头反映所传送内容的 MIME 类型。
注意事项:
您的源站 Web 服务器软件必须为每个响应设置
Content-Type
。许多 Web 服务器会自动设置Content-Type
标头,包括 NGINX、Varnish 和 Apache。使用 Google Cloud 控制台或 Google Cloud CLI 上传内容时,Cloud Storage 会自动设置
Content-Type
标头。Cloud Storage 始终向 Cloud CDN 提供
Cache-Control
标头。如果未明确选择值,它会发送默认值。 因此,除非您在 Cloud Storage 中明确调整了对象的缓存控制元数据,或者使用FORCE_CACHE_ALL
模式替换 Cloud Storage 发送的值,否则所有成功的 Cloud Storage 响应都会根据 Cloud Storage 默认值进行缓存。如果您要缓存
text/html
和application/json
内容类型,则必须在响应中设置显式Cache-Control
标头,以避免意外缓存某个用户的数据,并将其传送给所有用户。
如果响应可根据其 MIME 类型缓存,但 Cache-Control
响应标头为 private
或 no-store
,或标头为 Set-Cookie
,则不会缓存该响应。如需了解详情,请参阅可缓存性规则。
其他类型的内容,例如 HTML (text/html
) 和 JSON (application/json
) 不会被缓存默认情况下为成功响应。这些类型的响应通常是动态的(每个用户)。例如购物车、具有用户个性化的商品页面以及经过身份验证的 API 响应。但是,负缓存(如果启用)仍会导致它们针对某些状态代码进行缓存。
Cloud CDN 不会使用网址路径中的文件扩展名来确定响应是否可缓存,因为很多有效的可缓存响应没有反映在网址中。
可缓存的内容
Cloud CDN 会缓存满足本部分所列全部要求的响应。其中一些要求是 RFC 7234 中规定的,而其他要求则专门针对 Cloud CDN。
Cloud CDN 可能会定期更改其用于缓存内容的具体条件集。如果要明确阻止 Cloud CDN 缓存您的内容,请遵循 RFC 7234 中的准则,以确定如何指定保证不可缓存的响应。另请参阅基于源标头的不可缓存内容部分。
如果满足以下所有条件,则 Cloud CDN 会将响应存储在缓存中:
属性 | 要求 |
---|---|
来源 | 已启用 Cloud CDN 的后端服务、后端存储桶或外部后端 |
所响应的请求 | GET 请求 |
状态代码 |
|
时效性 | 响应具有含 对于没有存在时间的可缓存响应(例如具有 在 在 如果启用了负缓存并且状态代码与负缓存指定 TTL 的状态代码匹配,则即使没有显式新鲜度指令,响应也有资格进行缓存。 |
内容 | 对于 HTTP/1 源,响应必须包含有效的 对于使用更高级的 HTTP 协议版本(HTTP/2 及更高版本)的来源,响应无需包含此类标头。 |
大小 | 大小不超过大小上限。 对于大小介于 10 MiB 到 100 GiB 之间的响应,请参阅字节范围请求中所述的其他可缓存性限制。 |
对于 Cloud Storage 后端存储分区,请遵循以下其他建议:
将存储桶设为可公开读取。 我们建议使用这种方法来公开内容。如此设置时,互联网上的任何人都可以查看和列出您的对象及其元数据(不包括 ACL)。建议的做法是为公开对象使用专用的存储分区。
将个别对象设为可公开读取。我们不建议采用这种方法,因为它使用的是 Cloud Storage 专用的旧版权限系统。
请勿将对象存储在已启用请求者付款的存储桶中,也不要在 Virtual Private Cloud 服务边界内存储对象。
默认情况下,如果对象是公开的且未指定 Cache-Control
元数据,则 Cloud Storage 会向对象分配 Cache-Control: public, max-age=3600
标头。您可以使用 Cache-Control
元数据设置不同的值。
如需查看显示如何使用后端存储桶配置外部应用负载均衡器的示例,请参阅使用后端存储桶设置 Cloud CDN。
大小上限
Cloud CDN 会对每个响应强制执行大小上限。正文超出大小上限的任何响应都不会被缓存,但仍会传送给客户端。
大小上限的值取决于源服务器是否支持字节范围请求。
源站服务器支持字节范围请求 | 源站服务器不支持字节范围请求 |
---|---|
100 GiB(107,374,182,400 字节) | 10 MiB(10,485,760 字节) |
几乎所有现代 Web 服务器(包括 NGINX、Apache 和 Varnish)都支持字节范围请求。
基于源标头的不可缓存内容
某些检查会禁止系统对响应进行缓存。 Cloud CDN 可能会定期更改其用于缓存内容的具体条件集,因此,如果要明确阻止 Cloud CDN 缓存您的内容,请遵循标准 (RFC 7234) 中的准则,以确定如何指定保证不可缓存的响应。
如果 Cloud CDN 不符合可缓存的内容的要求,或者满足下述任一条件,则不会缓存该响应。
属性 | 要求 |
---|---|
来源 | 未启用 Cloud CDN 的后端服务或外部后端 |
Cookie | 具有 Set-Cookie 标头 |
Vary 标头 |
值不是 Accept 、Accept-Encoding 、Access-Control-Request-Headers 、Access-Control-Request-Method 、Origin 、Sec-Fetch-Dest 、Sec-Fetch-Mode 、Sec-Fetch-Site 、X-Goog-Allowed-Resources 、X-Origin ,或者配置为缓存键设置的一部分的标头之一。
|
响应指令 | 响应具有含 no-store 或 private 指令的 Cache-Control 标头(除非使用 FORCE_CACHE_ALL 缓存模式,在该模式下,Cache-Control 标头会被忽略) |
请求指令 | 请求包含 Cache-Control: no-store 指令 |
请求授权 | 请求具有 Authorization 标头,除非被响应 Cache-Control 替换。 |
大小 | 超过大小上限 |
如果存在 Cache-Control: no-store
或 private
,但内容仍在缓存中,则可能是由下列某种原因造成的:
- 已配置网址签名。
- 将 Cloud CDN 缓存模式设置为强制缓存所有响应。
防止缓存
要防止不公开信息缓存在 Cloud CDN 缓存中,请执行以下操作:
- 确保 Cloud CDN 缓存模式未设置为
FORCE_CACHE_ALL
模式,此模式会无条件缓存所有成功响应。 - 对于不应在 Cloud CDN 缓存中存储的响应,在响应中包含
Cache-Control: private
标头;对于不应在任何缓存(即便是网络浏览器缓存)中存储的响应,在响应中包含Cache-Control: no-store
标头。 - 不签署可访问不公开信息的网址。使用签名网址访问内容时,响应中无论是否有任何
Cache-Control
指令,都有可能被缓存。 - 当缓存模式设置为
USE_ORIGIN_HEADERS
或CACHE_ALL_STATIC
时,对于包含Authorization
请求标头的源站(缓存填充)请求,Cloud CDN 只会缓存包含public
、must-revalidate
或s-maxage
缓存控制指令的响应。这可以防止意外缓存每个用户的内容和需要进行身份验证的内容。FORCE_CACHE_ALL
缓存模式没有此限制。
自定义响应标头
借助自定义响应标头,您可以指定经典版应用负载平衡器添加到代理响应中的标头。借助自定义响应标头,您可以反映客户端、客户端地理数据和您自己的静态响应标头的缓存状态。
如需了解相关说明,请参阅配置自定义响应标头。
缓存键
Cloud CDN 缓存中的每个缓存条目都通过缓存键来标识。当请求进入缓存时,缓存会将请求的 URI 转换为缓存键,然后将该键与缓存条目的键进行比较。如果找到匹配的键,缓存将返回与该键关联的对象。
对于后端服务,Cloud CDN 默认使用完整请求 URI 作为缓存键。例如,https://example.com/images/cat.jpg
是 cat.jpg
对象的特定请求的完整 URI。该字符串用作默认缓存键。只有 URI 与该字符串完全相同的请求才视为匹配。URI 是 http://example.com/images/cat.jpg
或 https://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 部分 | 自定义 | 具有相同缓存键的网址示例 |
---|---|---|
协议 | 在缓存键中省略协议。 |
|
主机 | 在缓存键中省略主机。 |
|
查询字符串 | 在缓存键中省略查询字符串。 选择性地省略或包含查询字符串的各部分。 |
|
除了包含或省略整个查询字符串之外,您还可以借助包含列表和排除列表来使用查询字符串的各个部分。
查询字符串包含列表
您可以选择性地控制 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
,通常针对每位用户,例如在 OAuthBearer
令牌中CDN-Loop
Connection
Content-MD5
Content-Type
Cookie
Date
Forwarded
,通常针对各客户端或各代理From
Host
,因为此设置由配置 (cdnPolicy.includeHost
) 进行控制If-Match
、If-Modified-Since
或If-None-Match
Origin
Proxy-Authorization
Range
Referer
(或Referrer
)User-Agent
Want-Digest
- Django 和 Ruby on Rails 使用的
X-CSRFToken
和X-CSRF-Token
X-Forwarded-For
,通常针对各客户端或各代理X-User-IP
- 使用如下内容开头的任何标头:
Access-Control-
,例如Access-Control-Request-Headers
和Access-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-cache |
系统会忽略 no-cache 请求指令,以防止客户端可能向来源发起或强制重新验证。 |
系统会缓存具有
您可以根据后端将此设置替换为 |
public |
不适用 |
此指令不是可缓存性所必需的,但最佳做法是将它包含在应由代理缓存的内容中。 |
private |
不适用 |
具有
您可以根据后端将此设置替换为 |
max-age=SECONDS
|
系统会忽略 max-age 请求指令。返回缓存的响应就像此标头未包含在请求中一样。 |
具有 max-age 指令的响应缓存时间长达定义的 SECONDS。 |
s-maxage=SECONDS
|
不适用 |
具有
如果同时存在 具有此指令的响应不会过时传送。
|
min-fresh=SECONDS
|
系统会忽略 min-fresh 请求指令。返回缓存的响应就像此标头未包含在请求中一样。 |
不适用 |
max-stale=SECONDS
|
Cloud CDN 会采用此指令,并且仅在响应过时小于 |
不适用 |
stale-while-revalidate=SECONDS
|
不适用 |
具有
您可以通过对后端设置 |
stale-if-error=SECONDS
|
系统会忽略 stale-if-error 请求指令。返回缓存的响应就像此标头未包含在请求中一样。 |
此响应标头没有任何影响。 |
must-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-age
或 expires
)值提供的值允许自动重新验证用户生成的过时缓存内容。
Cloud CDN 收到请求时,它会查询相应的缓存条目并检查该条目的存在时间。如果缓存条目存在并且新鲜度足以满足要求,则可以从缓存中传送响应。但是,如果当前时间晚于过期时间,Cloud CDN 将尝试通过与您的其中一个后端连接来重新验证缓存条目。此操作在传送响应之前完成,除非您启用了在过时的情况下传送,在这种情况下会异步执行重新验证。
对于某些缓存模式,您可以设置 TTL 值。如需了解详情,请参阅使用 TTL 设置和替换。
缓存模式会影响确定新鲜度的方式。
缓存模式 | 验证行为 |
---|---|
CACHE_ALL_STATIC |
系统会查询源站标头(Cache-Control: s-maxage 、Cache-Control: max-age 或 Expires 标头)以确定新鲜度。对于静态内容,如果源站标头不存在,则配置的 default_ttl 会确定新鲜度。静态内容的时间晚于 default_ttl 后,Cloud CDN 会对其进行重新验证。 |
USE_ORIGIN_HEADERS |
Cloud CDN 缓存中的每个缓存条目都有一个过期时间,由 Cache-Control: s-maxage 、Cache-Control: max-age 或 Expires 标头根据 RFC 7234 定义。 |
FORCE_CACHE_ALL |
配置的 default_ttl 将确定新鲜度,而不是源站标头。内容的时间晚于 default_ttl 后,Cloud CDN 会对其进行重新验证。 |
如果存在多个标头,则 Cache-Control: s-maxage
优先于 Cache-Control: max-age
,Cache-Control: max-age
优先于 Expires
。
默认情况下,当过期时间值超过 30 天(2592000 秒)时,Cloud CDN 会将过期时间值视为 2592000 秒。不过即使 max-age
和 s-maxage
超过 30 天,下游客户端仍会看到其准确值。
逐出
我们无法保证缓存条目在过期之前一直保留在缓存中,因为非热门条目可以在随时过期之前被逐出,以便为新内容腾出空间。作为上限,系统会自动逐出 30 天内未被访问的缓存条目。
如需了解详情,请参阅驱逐和到期。
使用条件请求进行验证
Cloud CDN 可以尝试使用缓存的响应标头中的信息来向后端验证缓存条目。如果同时满足以下两个条件,则会出现这种情况:
- 之前缓存的响应具有
Last-Modified
或ETag
标头。 - 客户端请求是一个不包含
If-Modified-Since
或If-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 OK
或206 Partial Content
- 标头:
Accept-Ranges: bytes
- 标头:
Content-Length
;对于206 Partial Content
响应,是一个Content-Range
值,表示来源对象的完整长度。例如,Content-length: 0-100/999
可缓存,而Content-length: 0-100/*
不可缓存。 - 标头:带有强验证器的
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 字节)。
如果发生这种情况,并且响应在其他情况下可以满足正常的可缓存性要求,缓存会记录源服务器支持该缓存键的字节范围请求,并将源服务器的响应转发给客户端。
在缓存未命中时,缓存会检查是否已经确知源站服务器支持字节范围请求。如果已经确知源站服务器支持该缓存键的字节范围请求,则缓存不会将客户端请求转发到外部应用负载均衡器。 在这种情况下,缓存会针对内容的缺失部分发起自己的字节范围缓存填充请求。
当 Cloud CDN 发起自己的字节范围缓存填充请求时,源服务器会返回 206 Partial Content
响应。如需在缓存时考虑 206 Partial Content
响应,该响应必须包含含 complete-length
指令的 Content-Range
标头,且该指令不包含星号,例如 0-100/999
。然后,Cloud CDN 会缓存返回的 206 Partial Content
响应,并使用该响应来响应未来对该内容的客户端请求。
只有当收到的 206 Partial Content
响应是对缓存发起的字节范围请求作出的响应时,缓存才会存储该响应。除非先前有记录表明,源站服务器支持相应缓存键的字节范围请求,否则缓存不会发起字节范围请求,因此,对于大于 1 MB 的内容,只有在该内容被第二次访问时,给定的缓存才会存储该内容。
由于 Cloud CDN 具有分布式特性,因此 Cloud CDN 有时可能会从每个位置多次从源站提取最后一个数据块。这只会影响每个缓存键的前几个请求。
请求折叠(合并)
请求折叠(也称为“合并”)将针对同一缓存键的多个用户发起的缓存填充请求主动折叠为每个边缘节点的一个源站请求。这样可以主动减少源站负载,适用于项请求(直接提取响应)和块请求(Cloud CDN 使用 Range
请求更高效地提取较大对象)。
请求折叠默认启用。
折叠的请求的行为方式如下:
- 折叠的请求会记录面向客户端的请求和(折叠的)缓存填充请求。
- 折叠会话的标头用于发出源站填充请求。
- 不属于缓存键的请求特性(例如
User-Agent
或Accept-Encoding
标头)仅反映折叠会话的标头。 - 无法折叠缓存键不同的请求。
下图展示了请求是如何合并的:
相比之下,如果停用了请求折叠或者请求无法合并,源站请求和响应的数量可以等于尝试检索未缓存对象的客户端的数量。
对于所有类型的请求,默认情况下会启用折叠。对于项请求类型,您可以停用折叠。我们建议在对延迟时间高度敏感且无需考虑源站负载的场景中(例如广告投放)停用项请求折叠。
下表总结了不同请求类型的默认行为和可配置性。
请求类型 | 默认行为 | 可配置 | 折叠的优势 |
---|---|---|---|
块请求 | 已启用 | 否 | 可显著减少源站带宽 |
项请求 | 已启用 | 是 | 可减少源站请求量 |
使用 Google Cloud CLI 为引用 Cloud Storage 存储桶的后端存储桶停用项请求折叠:
gcloud
使用 gcloud compute backend-services
或 backend-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-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 发起验证请求或字节范围请求时,它并不会包含特定于客户端的标头,比如 Cookie
或 User-Agent
。
在 Cloud Logging httpRequest.userAgent
字段中,Cloud-CDN-Google
表示请求由 Cloud CDN 发起。
绕过缓存
通过缓存绕过,包含特定请求标头的请求可以绕过缓存,即使之前已缓存内容也可以如此。
本部分介绍了如何绕过包含 HTTP 标头(例如 Pragma
和 Authorization
)的缓存。如果您要确保用户或客户始终重新从来源服务器提取最新内容,则此功能非常有用。建议您在测试、设置暂存目录或脚本时执行此操作。
如果指定的标头匹配,则系统会为所有缓存模式设置(即使是 FORCE_CACHE_ALL
)绕过缓存。如果指定的标头在许多请求中很常见,则缓存绕过会导致大量缓存未命中。
准备工作
确保已启用 Cloud CDN;如需了解相关说明,请参阅使用 Cloud CDN。
如有必要,请更新到 Google Cloud CLI 的最新版本:
gcloud components update
配置缓存绕过
您最多可以指定五个 HTTP 标头名称。值不区分大小写。 标头名称必须是有效的 HTTP 标头字段令牌。标头名称不能在已添加标头的列表中出现多次。 如需了解有效标头名称的规则,请参阅自定义标头的工作原理。
控制台
- 在 Google Cloud 控制台中,前往负载均衡页面。
- 点击外部应用负载均衡器的名称。
- 点击修改 。
- 在后端配置中,选择一个后端,然后点击修改 。
- 确保选择启用 Cloud CDN。
- 在窗口底部,点击高级配置。
- 在绕过请求标头的缓存下,点击添加标头。
- 输入标头名称,例如
Pragma
或Authorization
。 - 点击更新。
- 再次点击更新。
gcloud
对于后端存储桶,请使用带有 --bypass-cache-on-request-headers
标志的 gcloud compute backend-buckets create 或 gcloud compute backend-buckets update 命令。
对于后端服务,请使用带有 --bypass-cache-on-request-headers
标志的 gcloud compute backend-services create 或 gcloud 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 create 或 gcloud compute backend-buckets update 命令。
对于后端服务,请使用带有 --no-bypass-cache-on-request-headers
标志的 gcloud compute backend-services create 或 gcloud 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" }
后续步骤
- 如需了解缓存模式如何让缓存内容更轻松,请参阅使用缓存模式。
- 如需为 HTTP(S) 负载均衡实例和存储分区启用 Cloud CDN,请参阅使用 Cloud CDN。
- 如需了解如何使缓存失效,请参阅缓存失效操作概览。
- 如需查找 GFE 入网点,请参阅缓存位置。