
「上了 CDN 还是慢」是 WordPress 站点很常见的反馈。CDN 只有在命中边缘缓存时才快;一旦请求回到源站(回源),速度就取决于源站生成页面的时间,以及 CDN 节点到源站的网络链路。排查回源慢,核心是回答三个问题:哪些请求在回源、为什么回源、回源的那一段慢在哪里。下面按这个顺序给出可直接执行的步骤。
第 1 步:确认请求有没有命中
先看响应头。不同 CDN 的字段名不同,但都会标明缓存状态:
curl -sI https://example.com/ | grep -iE "cf-cache-status|x-cache|age|cache-control|via|server"
- Cloudflare:
cf-cache-status: HIT为命中;MISS、EXPIRED表示本次回源;DYNAMIC表示该资源不在缓存范围内(默认情况下 HTML 就是 DYNAMIC);BYPASS通常是源站的 Cache-Control 头或绕过规则要求不缓存。 - 阿里云、腾讯云等国内 CDN 多用
X-Cache、Via等字段,含有 HIT 或 MISS 字样,具体字段以服务商文档为准。 Age表示对象已在缓存中存在的秒数。连续请求时 Age 始终为 0 或不存在,说明没有被缓存。
分别检查 HTML 页面、CSS/JS、图片和字体。很常见的情况是静态资源已经命中,而 HTML 全部回源——这时用户看到的首字节时间就等于源站速度加上回源时间。
第 2 步:把边缘和源站分开测
先测经过 CDN 的完整耗时:
curl -o /dev/null -s -w "connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer}\n" https://example.com/
再绕过 CDN 直连源站(临时把域名指向源站 IP,不改 DNS;如果源站证书与域名不匹配,测试时可临时加 -k):
curl -o /dev/null -s -w "ttfb:%{time_starttransfer}\n" --resolve example.com:443:源站IP https://example.com/
- 直连源站也慢:瓶颈在源站本身,按 TTFB 的思路排查页面缓存、PHP 与数据库。
- 直连源站快,经 CDN 回源慢:问题在回源链路,例如节点与源站跨地域、回源协议或端口配置不当、源站防火墙对 CDN 节点限速。
- 第一次慢、之后快:缓存能命中,但缓存时间太短或被频繁清理。
第 3 步:检查源站返回的缓存头
CDN 是否缓存、缓存多久,很大程度上取决于源站返回的 Cache-Control、Expires 和 Set-Cookie:
- HTML 返回
no-cache、private或max-age=0时,即使 CDN 配了缓存 HTML,也可能因为遵循源站头而不缓存。WordPress 对登录用户和部分动态页面会主动发送这类头。 - 响应中带有
Set-Cookie时,多数 CDN 默认不缓存。常见来源是统计插件、多语言插件、会话或购物车插件,要找出是谁给所有页面都设置了 Cookie。 - 静态资源建议设置长期缓存,并在文件名或查询参数中带版本号,更新时自然换 URL,不必频繁清理。
Nginx 中为静态资源设置长期缓存的示例:
location ~* \.(css|js|png|jpg|jpeg|gif|webp|avif|svg|woff2)$ {
expires 365d;
add_header Cache-Control "public, max-age=31536000, immutable";
}
第 4 步:缓存键有没有被打散
即使 HTML 可以缓存,如果缓存键里包含太多变量,命中率仍然很低:
- 营销参数(
utm_source、gclid、fbclid等)会让同一页面产生大量不同 URL,可以在 CDN 上配置忽略这些参数; - 按 Cookie 或 User-Agent 区分缓存时,变体数量会成倍增加,只有在确实存在移动端独立模板等需求时才这样做;
- 多语言站点应按 URL 路径或子域区分语言,而不是用 Cookie 切换,否则既难以缓存,也不利于搜索引擎收录。
第 5 步:配置 HTML 缓存与排除规则
想让 HTML 在边缘命中,需要在 CDN 上为 HTML 单独设置缓存规则,同时排除不能缓存的路径和状态:
- 必须排除:
/wp-admin/、/wp-login.php、文章预览链接,以及 WooCommerce 的购物车、结账、我的账户页面; - 带有
wordpress_logged_in_、wp-postpass_、woocommerce_items_in_cart等 Cookie 的请求应绕过缓存; - 边缘缓存时间可以设得较长,但必须接好发布和更新时的自动清理(缓存插件的 CDN 集成或调用 CDN 清理接口),否则会出现「改了内容前台不变」。
第 6 步:检查回源链路本身
- 地域:源站在海外而访客在国内(或反过来),回源跨境本身就慢。可以考虑就近部署源站,或启用 CDN 的分层缓存(中间层回源)功能,减少直接回源的节点数量。
- 协议与端口:确认回源协议(HTTP/HTTPS)与源站监听端口一致,源站证书有效、开启了 keep-alive,避免每次回源都先经历一次 301 跳转。
- 源站防护:源站防火墙、WAF 或面板安全插件可能把 CDN 节点 IP 当作高频访问而限流,造成间歇性变慢或 5xx。应把 CDN 回源 IP 段加入白名单,并在源站通过真实 IP 头记录访客地址。
- 超时与错误:查看 CDN 日志中的回源耗时与状态码,偶发的 502、504 往往对应源站 PHP-FPM 进程排队。
第 7 步:验证与持续观察
- 对首页、文章页、分类页各请求 3 次,记录命中状态和首字节时间;
- 发布一篇测试文章,确认相关页面的缓存被清理、新内容可见;
- 登录后台再访问前台,确认不会看到缓存的未登录页面,也不会把登录态页面缓存给访客;
- 在 CDN 控制台按天查看命中率和回源流量的变化,作为后续调整的依据。
Cache-Control 各项指令的准确含义可参考 MDN 的 Cache-Control 文档。缓存分层的整体思路见 WordPress CDN 与缓存加速专题;缓存插件出问题时的处理顺序见 缓存性能排障手册;回源问题解决之后,前端指标的检查项见 Core Web Vitals 实践清单。
常见问题
CDN 能缓存整个 WordPress 站点吗?
内容页、分类页可以缓存,但后台、登录、预览、购物车、结账和会员中心必须排除。按路径和 Cookie 配置规则,比整站一刀切更安全。
清理缓存后为什么会短时间变慢?
清理之后,第一批请求都要回源重新生成,这是正常现象。可以只清理与本次变更相关的 URL,或在发布后预热重要页面。
源站和 CDN 必须用同一家云服务商吗?
不是必须。关键在于回源网络质量和地域距离,可以用直连测试和 CDN 的回源日志来评估。
回源问题通常同时涉及 CDN 配置、源站缓存和防火墙,如果需要帮忙梳理,可以 申请免费诊断。
