排查 Cloud CDN 问题

如果您在使用 Cloud CDN 时遇到以下问题,下面介绍的这些问题排查步骤可能会派上用场。

如果您遇到的问题与外部后端有关,另请参阅排查外部后端和互联网 NEG 的问题

常见问题和解决方案

本部分介绍了一些常见问题及其解决方案。

响应未被缓存

如果响应未被缓存,请首先检查是否为后端服务或后端存储分区启用了 Cloud CDN。当您启用 Cloud CDN 时,可能需要等待几分钟时间,然后系统才能开始缓存响应。

Cloud CDN 仅缓存具有可缓存内容的响应。HTTP 响应标头以及后端配置将传达这些信息。使用 cdn_cache_status 配置自定义响应标头时,您可以在 Cloud CDN 日志中观察缓存状态,并确定响应是否因缓存未命中而传送。

如果某网址的响应没有被缓存,请检查为该网址返回了哪些标头,以及后端的可缓存性如何配置

您可以通过以下几种方式检查响应标头:

以下示例演示了如何使用 curl 来检查 http://example.com/style.css 的 HTTP 响应标头:

curl -s -D - -o /dev/null http://example.com/style.css

输出:

HTTP/1.1 200 OK
Date: Tue, 16 Feb 2016 12:00:00 GMT
Content-Type: text/css
Content-Length: 1977
Via: 1.1 google

将这些标头与可缓存的内容要求进行比较后可以看出,响应缺少必要的 Cache-Control 标头(假设缓存模式设置为 USE_ORIGIN_HEADERS)。

设置标头的方法取决于源服务器的类型。如果您在 Compute Engine 上运行 Web 服务器,请参阅 Web 服务器软件的文档,详细了解如何配置响应标头。对于 Cloud Storage,如果将对象标记为公开共享,则系统会发送相应的标头。

重新配置源服务器以添加所需的标头后,您可以再次使用 curl 来检查结果:

curl -s -D - -o /dev/null http://example.com/style.css

输出:

HTTP/1.1 200 OK
Date: Tue, 16 Feb 2016 12:00:30 GMT
Content-Type: text/css
Content-Length: 1977
Cache-Control: max-age=86400,public
Via: 1.1 google
curl -s -D - -o /dev/null http://example.com/style.css

输出:

HTTP/1.1 200 OK
Date: Tue, 16 Feb 2016 12:00:31 GMT
Content-Type: text/css
Content-Length: 1977
Cache-Control: max-age=86400,public
Via: 1.1 google
curl -s -D - -o /dev/null http://example.com/style.css

输出:

HTTP/1.1 200 OK
Date: Tue, 16 Feb 2016 12:00:30 GMT
Content-Type: text/css
Content-Length: 1977
Cache-Control: max-age=86400,public
Via: 1.1 google
Age: 2

此示例中的最后一个响应包含一个 Age 标头。Cloud CDN 会在其从缓存传送的响应中添加一个 Age 标头。此处,该标头表明,系统已使用 2 秒前创建的缓存条目从缓存中成功传送了响应。

此外,如果在后端实例上启用了 ETags,则 Cloud CDN 会依照 ETag 来确认对象的新鲜度。如果后端实例在同一对象上提供了多个不同的 ETag,则 Cloud CDN 会将不匹配项计为缓存未命中并刷新该对象。为避免这种情况,后端实例必须提供相同的 ETag,否则就必须停用 ETag。

如需检查这一点,请重复运行 curl 并观察 ETag 值的变化。

curl -s -D - -o /dev/null http://example.com/image.png

输出:

HTTP/2 200
date: Fri, 20 Mar 2020 15:02:30 GMT
server: Apache
strict-transport-security: max-age=31536000; includeSubDomains
last-modified: Mon, 16 Mar 2020 04:20:59 GMT
etag: "10f-5a0f1256f1402"
accept-ranges: bytes
content-length: 271
cache-control: public, max-age=864000
expires: Mon, 30 Mar 2020 15:02:30 GMT
vary: Accept-Encoding
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
content-type: image/png
via: 1.1 google
alt-svc: clear
curl -s -D - -o /dev/null http://example.com/image.png

输出:

HTTP/2 200
date: Fri, 20 Mar 2020 15:03:11 GMT
server: Apache
strict-transport-security: max-age=31536000; includeSubDomains
last-modified: Mon, 16 Mar 2020 04:18:31 GMT
etag: "10f-5a0f11ca09b7a"
accept-ranges: bytes
content-length: 271
cache-control: public, max-age=864000
expires: Mon, 30 Mar 2020 15:03:11 GMT
vary: Accept-Encoding
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
content-type: image/png
via: 1.1 google
alt-svc: clear

Cloud Storage 对象无法访问

要提供对 Cloud Storage 中对象的访问权限,您必须配置签名网址或向存储分区及其所有对象授予 allUsers 的公开访问权限。

如果您决定提供 allUsers 访问权限,可以按照以下步骤验证对象级访问权限。

控制台

  1. 在 Google Cloud 控制台中打开 Cloud Storage 浏览器

    打开 Storage 浏览器

  2. 点击存储分区以查看存储分区详情页面。

  3. 公共访问权限列中,将指针悬停在感叹号图标上,然后点击修改访问权限

    对于存储分区中的每个对象,请确保设置以下权限:

    • 实体:User
    • 名称:allUsers
    • 访问权限:Reader

如需详细了解 Cloud Storage 的访问权限控制,请参阅 Cloud Storage 的 Identity and Access Management (IAM) 文档

如需详细了解签名网址,请参阅使用签名网址

如果对象可访问但未被缓存,请参阅响应未被缓存

缓存了不公开的内容,或者缓存的内容不正确

如果您知道源服务器为什么传送了不公开或不正确的内容,并且您可以解决该问题,则可以通过以下过程使 Cloud CDN 缓存失效:

  1. 确保源服务器不再返回不公开或不正确的内容。
  2. 请求缓存失效操作,以指示 Cloud CDN 停止传送缓存的内容。

如需了解详情,请参阅缓存失效操作概览

Cloud CDN 仅缓存包含可缓存内容的响应,并且仅从缓存中传送存在时间不超过响应中指定的到期时间的响应。如果您不知道为什么内容被缓存,或无法适当地解决相关问题,则建议您在了解并解决问题之前先停用 Cloud CDN,等问题得到解决后再重新启用。如需详细了解缓存的内容以及缓存时长,请参阅缓存概览

缓存命中率低

为了提高性能和可伸缩性,请务必优化缓存命中率。如果低于预期的缓存命中率,请确保遵循优化缓存命中率的最佳做法。

使用下表了解缓存命中率低的一些可能原因以及可行的修复方法。

原因 注释 可修复漏洞数
您的内容不可缓存 可缓存响应是一种可供 Cloud CDN 存储的 HTTP 响应。 确保您的内容可缓存
缓存模式不是您的应用的最佳选择。 Cloud CDN 有多种缓存模式 如果您未使用缓存控制标头来控制缓存行为,则建议的最佳做法是让 Cloud CDN 缓存所有静态内容。
流量少。 在测试和实验期间,您生成的流量可能较低。Google 具有全球分布式缓存,来自不同地理位置的请求会转到不同的 Google 前端位置。在每个前端位置,Google 可能会缓存多个离散实例。
  • 确保向 Google 发送足够的流量,以填充所有相关缓存。
  • 在测试期间,请务必按网址对流量进行分片,使得每组请求的所有流量都流向 Google。请勿将每个请求随机分片到不同的 CDN 提供商。
特定网址的响应未被缓存。 Cloud CDN 将完整的请求 URI 合并到其缓存键中,因此 http://example.com/cat.jpg?color=orangehttp://example.com/cat.jpg?color=gray 各自具有单独的缓存条目。 始终对给定的资源使用单一网址。

如果您需要将参数传递给在某个可缓存页面上运行的 JavaScript,请考虑使用片段标识符(而非查询字符串)。

由于 Vary 标头字段,缓存进行了不必要的分片。 响应中的 Vary 标头字段描述了请求消息的哪些部分(方法、Host 标头字段和请求目标除外)可能会影响源服务器选择和代表响应的过程。例如,如果向可以处理压缩响应的客户端和无法处理压缩响应的客户端传送不同内容,则可能需要使用 Vary: Accept-Encoding 标头。 请仅在必要时使用 Vary 响应标头。
您未使用自定义缓存键 默认情况下,Cloud CDN 使用完整的请求网址来构建缓存键。您可以自定义缓存键以包含或省略协议、主机或查询字符串中的任意一项或多项。例如,如果两个网域使用相同的静态内容,则可以创建省略主机字段的自定义缓存键。 根据需要使用自定义缓存键。

同一内容存在多个缓存填充

通常,您可以通过延长可缓存响应的过期时间来减少缓存填充的数量。带有 Cache-Control: public, max-age=86400 的响应的缓存填充数量少于带有 Cache-Control: public, max-age=1 的响应,除此之外其他方面都保持不变。

如需详细了解过期时间,请参阅过期时间和验证请求。如需了解如何配置适当的响应标头,请参阅您的 Web 服务器软件的文档。

Cloud CDN 在全球范围内运行大量缓存,旧的缓存条目会被定期逐出,以便为新内容腾出空间。因此,每个资源有多个缓存填充属于正常操作。

未执行压缩

Cloud CDN 为无法压缩其响应的源服务器提供动态压缩。我们建议您尽可能在源服务器使用压缩,因为它可以降低缓存填充费用。

如果 Cloud CDN 传送的响应未被压缩,但本应进行压缩,请检查您的实例上运行的网络服务器软件是否配置为会对响应执行压缩。默认情况下,某些 Web 服务器软件会对包含 Via 标头的请求自动停用压缩功能。Via 标头的存在表明请求是由代理转发的。外部应用负载均衡器等 HTTP 代理会根据 HTTP 规范的要求为每个请求添加 Via 标头。如需启用压缩功能,您可能必须覆盖 Web 服务器的默认配置,以指示其对响应进行压缩(即便是请求中包含了 Via 标头)。

如果您使用的是 nginx Web 服务器软件,请修改 nginx.conf 配置文件以启用压缩功能。此文件的位置取决于 nginx 的安装位置。在大部分 Linux 发行版中,此文件的存储位置都是 /etc/nginx/nginx.conf

如需将 nginx 压缩功能用于外部应用负载均衡器,请将以下两行内容添加到 nginx.conf 的 http 部分中:

gzip_proxied any;
gzip_vary on;
  • 即使对于外部应用负载均衡器等代理转发的请求,第一行内容也可以启用压缩功能。

  • 第二行代码用于将 Vary: Accept-Encoding 标头添加到响应。Vary: Accept-Encoding 用于向缓存代理(例如 Cloud CDN)发送通知,告知它们应为可压缩资源的已压缩和未压缩变体保留单独的缓存条目。

修改 nginx.conf 之后,您需要重启 nginx,这样新配置才能生效。在大部分 Linux 发行版中,您可以通过运行 sudo service nginx restart/etc/init.d/nginx restart 来重启 nginx。

响应以 byte_range_caching_aborted 错误终止

当 Cloud CDN 汇总来自多个字节范围请求的响应时,它会比较 ETagLast-Modified 响应标头,以此来检查这些范围是否来自相同版本的资源。如果 Cloud CDN 发现任一标头的值与已传送给客户端的范围不一致,它将取消响应。

如果您发现响应意外终止、Cloud Logging 日志条目具有 byte_range_caching_aborted statusDetails,或者您的实例返回了 412 Precondition Failed 响应,请确保在所有虚拟机 (VM) 实例上运行的 Web 服务器软件会为给定资源返回相同的 ETagLast-Modified 值。

从磁盘传送文件时,Web 服务器软件通常会从文件的修改时间得出 ETagLast-Modified 值。在这种情况下,您可以通过对所有实例使用相同的映像来确保虚拟机实例报告一致的值。如需详细了解您的 Web 服务器软件如何确定 ETagLast-Modified 值,请参阅您的 Web 服务器软件文档。

签名 Cookie 问题排查

在您使用签名 Cookie 时,可能会发生以下问题。

编码

生成签名时,请求会因签名不匹配而遭到意外拒绝。

URLSignature 值进行编码时,请确保使用 base64 的可在网址中安全使用的变体。如果生成的字符不可在网址中安全使用,则标准 base64 会失败。系统接受填充。

签名

您的请求被 Cloud CDN 拒绝。

  • 确保您使用的签名算法是 HMAC-SHA-1,而不是 HMAC 的其他变体。

  • 确认 Cloud CDN 使用的 KeyName 参数(注意此参数区分大小写)是否与后端服务或后端存储分区的有效键名相匹配。

  • 请勿在生成 URLPrefix 和为其签名时对查询参数进行签名。确保 URLPrefix 仅包含网址的架构、主机和(部分)路径组成部分。

  • 确保签名块(URLPrefixExpiresKeyNameSignature 本身)是 Cookie 中由 : 分隔的各个部分中的最后一部分。

  • 确保 URLPrefixExpiresKeyNameSignature 按照此顺序排列。

  • 请勿在签名 Cookie 中 URLPrefix 的末尾处添加星号 (*) 字符。

Cookie

  • 通常情况下,浏览器将各网域的 Cookie 大小限制为 4 KB,各网域的 Cookie 总数不得超过 50 个。记好您要签发并要求客户端发送的其他 Cookie,因为许多 Web 服务器也有最大请求标头限制。

  • 确保您使用英文冒号字符 (:)、Unicode 编码的圆点 U+003A 作为签名 Cookie 中指定参数的分隔符,不能使用 & 字符。

  • 确保您签发的 Cookie 中的 Expires 时间戳不会过短。如果有效期短于 1-2 分钟,可能很容易在签发方应用与 Cloud CDN 基础架构之间造成时钟偏差问题。

  • 请确保您没有为具有不同值的相同 DomainPath 设置多个 Cookie。为每位用户设置一个 Cookie,并使用包含用户需要访问的所有内容的网址前缀值。

错误消息

本部分介绍了一些常见错误消息以及如何解决这些错误。

缓存失效操作错误

错误代码 备注
Invalid value for field 'resource.path'

路径值的格式无效。路径必须以 / 开头,不能包含 ?#,并且必须只有一个 *(必须作为 / 之后的最后一个字符)。

路径长度不能超过 1024 个字符。如果您看到此错误,请检查路径值并更正任何格式错误。

此错误仅与路径的格式相关。即便路径不存在,但只要其格式有效,该路径也会被视为有效。

Rate Limit Exceeded Cloud CDN 会限制可以执行缓存失效操作的速率。每分钟只允许执行一次失效操作。 但是,每个操作都可以指定与任意数量的对象匹配的路径模式。

已知问题

  • 缓存失效操作的速率受限制,每分钟只能对每个网址映射执行一次失效操作。

    解决方法:请等待至少一分钟,然后再尝试使另一个网址映射失效。

    如需详细了解缓存失效的速率限制,请参阅限制