1.
要点:缓存能显著降低延迟和降低源站负载,但错误的请求头或配置会导致命中率低、旧内容被缓存或频繁回源。调试的目标是理解来源头(origin response headers)、边缘响应(edge headers)和客户端请求(client request headers)三方交互并根据业务调整缓存策略。
结果预期:通过一套可复用的检查清单,可以定位缓存 MISS 的原因、验证缓存指令是否被 CDN 或浏览器尊重,并提出可执行的配置修改。
2.
步骤:
- 浏览器:打开 Chrome/Edge 的 DevTools Network 面板,勾选 Preserve log,查看每次请求的 Request Headers 与 Response Headers、Status、Size(包含 from cache 或 304)。
- 命令行:curl -I -v https://example.com/asset.js 用于查看响应头,curl -H "Cache-Control: no-cache" 可以模拟客户端强制验证。
- CDN 控制台/日志:登录 CloudFront / Cloudflare /Fastly /Akamai 控制台,查看边缘缓存命中率、缓存日志(如果开启)与缓存键配置。
3.
操作:
- 在本地或通过直接访问源站(绕过 CDN)执行:curl -I https://origin.example.com/path/file.css
- 关注头部:Cache-Control、Expires、ETag、Last-Modified、Vary、Surrogate-Control(用于 CDN 特定指令)。例如:Cache-Control: public, max-age=86400, s-maxage=86400。
- 确认无意的 Set-Cookie、Authorization 或 Cache-Control: private/no-store,这些会阻止边缘缓存。
4.
操作:
- 访问通过 CDN 的 URL:curl -I https://www.example.com/path/file.css
- 查找 CDN 特定头:Cloudflare 会有 CF-Cache-Status: HIT/MISS, CloudFront 有 X-Cache/Time/Hit 或 X-Cache: Hit from cloudfront, Fastly 有 X-Served-By、X-Cache。示例:Age: 123 表示缓存已存在 123 秒。
- 对比源站与边缘:如果边缘没有你在源站设置的 Cache-Control,则可能被 CDN 配置或边缘规则覆盖。
5.
操作:
- 模拟强制验证:curl -H "Cache-Control: no-cache" -I https://www.example.com/asset.js 观察是否返回 304 或回源。
- 使用条件请求测试 304:先获取 ETag:curl -I ... 得到 ETag:"abcd", 再执行 curl -H 'If-None-Match: "abcd"' -I ...,如果返回 304,说明源站正确支持条件验证。
- 测试带/不带 Cookie:curl -b "session=xxx" -I ...,如果含 Cookie 导致 MISS,考虑在 CDN 配置中忽略特定 Cookie 或设定缓存键规则。
6.
检查项:
- 响应头包含 Set-Cookie 或 Cache-Control: private/no-store。
- URL 中包含动态查询参数且 CDN 配置将其视为缓存键的一部分。
- CDN 的默认规则覆盖了源站缓存头(例如 Cloudflare 缺省缓存策略或 Page Rules)。
- 资源通过 Authorization 验证或是带上不必要的 Cookie,导致边缘不缓存。
7.
Nginx 示例(static 文件长期缓存 + 指纹化):
location ~* \.(css|js|jpg|png|svg)$ { expires 365d; add_header Cache-Control "public, max-age=31536000, immutable"; }
Apache 示例(.htaccess):
S3 + CloudFront:在上传 S3 的对象时设置 Metadata Cache-Control: public, max-age=31536000;在 CloudFront 中使用 Origin Response header 改写或设置缓存策略。
8.
策略:
- 静态且版本化资源:Cache-Control: public, max-age=31536000, immutable。
- 可缓存但可能更新的资源:Cache-Control: public, max-age=3600, stale-while-revalidate=30, stale-if-error=86400。
- 私有用户数据:Cache-Control: private, max-age=0, no-cache(或直接不缓存)。
9.
步骤:
- 确认 CDN 缓存键默认包含 Host + Path + QueryString(或不包含)。在 CloudFront、Cloudflare、Fastly 中可以分别配置是否包含查询字符串或只包含白名单参数。
- 策略建议:对于文件版本通过文件名做版本控制(/v1.2.3/app.js),避免使用 query string 作版本(/app.js?v=123),或在 CDN 上仅把 v 参数列入缓存键。
- 对于动态参数(如 utm_*)应在 CDN 侧忽略它们以避免缓存碎片化。
10.
实操:
- CloudFront:使用 AWS Console 或 aws cli 创建 invalidation:aws cloudfront create-invalidation --distribution-id EXXXX --paths "/path/*"
- Cloudflare:Dashboard 或 API:curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" -H "Authorization: Bearer
- Fastly/Akamai:使用各自 API/控制台发起清理请求。优先使用按路径清除而非全量清除。
11.
指标:
- 边缘命中率(Cache Hit Ratio)与回源请求数。
- 请求延迟(来自边缘与直接回源的对比)。
- 使用 CDN 的分析面板或自建日志(Edge logs)定期查看热点资源的命中率并调整 TTL。
12.
命令:
- 查看边缘响应头:curl -I -L https://www.example.com/static.js
- 模拟条件请求:curl -I -H 'If-None-Match: "etagvalue"' https://www.example.com/static.js
- 强制回源验证:curl -I -H 'Cache-Control: no-cache' https://www.example.com/static.js
13.
答:常见原因包括:CDN 配置覆盖源站头(例如 Cloudflare 的“Origin Cache Control”设置)、CDN 的缓存策略或 Page Rules 会强制设置自己的一套策略、或边缘规则(Edge Workers)在请求到达边缘时改写了头。排查方法:直接访问 origin(绕过 CDN)确认源站头;查看 CDN 控制台的缓存策略与规则;检查是否有边缘函数/worker 改写头部。
14.
答:按步骤检查:1) 使用 curl -I 查看响应是否含有阻止缓存的头(Set-Cookie、Cache-Control: private/no-store);2) 检查请求是否带有 Cookie 或 Authorization;3) 查看 CDN 的缓存键设置(是否包含动态 query 或 Cookie);4) 检查资源是否有 Vary: Accept-Encoding 类似导致分裂;5) 查看 CDN 日志或 X-Cache/CF-Cache-Status 是否显示 MISS 并查找原因字段。
15.
答:Cache-Control 决定缓存策略(是否缓存与多长时间)。ETag 与 Last-Modified 用于条件请求(If-None-Match / If-Modified-Since),当客户端或 CDN 进行重新验证时,源站可返回 304 表示未改动,从而避免发送完整响应。推荐做法:对可缓存资源同时设置合理的 Cache-Control(短 TTL 或 s-maxage)并保留 ETag/Last-Modified 以支持 revalidation。对于长期不可变资源,使用文件指纹并设置长 TTL,可省去 ETag。
