没有不值得去解决的问题,也没有不值得去学习的技术!

WordPress 发布新文章后首页仍是旧内容?EdgeOne 与 Cloudflare 将首页和 Sitemap 缓存缩短到 2 小时实测

图 2:EdgeOne 规则编辑界面,首页与 Sitemap 在同一条规则中分别设置 2 小时节点缓存 TTL。

作者:

,

WordPress CDN 与全球加速实战

图16:浏览器访问正常,网站全球访问成功

(1) 从阿里云 DNS 到 Cloudflare 全球加速的完整迁移实战记录

这一套规则遵循 Cloudflare + WordPress 标准 CDN 架构:

(2) Cloudflare SSL/TLS 与 Cache Rules 配置实战

图12:评论实时生效

(3) WordPress + Cloudflare 推荐配置与 Cache Rules 实战优化(SSL / API / 缓存闭环完整记录)

CDN上线后的boce数据

(4) CDN 上线前后性能对比实测:WordPress 缓存误判修正与真实加速效果验证

【图9:boce 测试 cn-test,灰云直连阿里云 ECS,平均响应 0.478s】

(5) Cloudflare 免费版适合中国大陆 WordPress 主站吗?从缓存 HIT 到灰云直连阿里云 ECS 的实测复盘

【图1:腾讯云 EdgeOne 产品页,选择“立即使用”】

(6) 从 Cloudflare Free 迁移到腾讯云 EdgeOne:一次 WordPress 主站国内外加速实战

【图2:EdgeOne 上线后 boce 第二次测试,平均响应 0.354s,不可访问 2 个】

(7) Cloudflare Free 迁移到 EdgeOne 后到底快了多少?WordPress CDN 三阶段 boce 与 WebPageTest 实测对比

[图2,EdgeOne 昨日 L7 访问流量,显示 6.56 GB]

(8) EdgeOne 流量成本排查:将 WordPress uploads 静态资源迁移到 Cloudflare media 子域名

【图3,EdgeOne 301 请求的 URL Path 排行,集中在 /wp-content/uploads/ 图片路径】

(9) WordPress 图片迁移到 media 子域名后,EdgeOne 仍然出现大量 301 的排查与处理记录

图4:Cloudflare Edge TTL 配置、Cloudflare Browser TTL 配置

(10) WordPress Media CDN 迁移后的 Cloudflare Cache Rules 调整记录

[图4:EdgeOne 按 URL path 开始于 /en/ 筛选后的流量截图]

(11) EdgeOne 流量成本控制决策:是否将英文站从 /en/ 迁移到 en.shuijingwanwq.com

[图3:执行核心升级时返回 524 No Reason Phrase]

(12) WordPress 核心升级反复 524 与“另一更新正在进行”的排查记录

【图 10:新证书 SAN 信息截图,显示已经包含 en.shuijingwanwq.com】

(13) OneinStack 现有 Nginx 虚拟主机追加域名并重签 SSL 证书的一次实操记录

【图 8,curl 验证 www 与 en 的 html lang、canonical 均正确】

(14) WordPress Polylang 英文站从 /en/ 迁移到 en 子域名:W3TC 与 Redis 缓存问题排查

【图 14,最终回归验证:en 首页和文章页 Cloudflare HIT,lang 与 canonical 正确】

(15) 将 Polylang 英文子域名接入 Cloudflare:HTML 缓存、登录绕过与后台入口收敛

【图1:浏览器开发者工具中,旧 /en/ 首页返回 301,随后成功加载 en 子域名英文首页】

(16) WordPress 英文站从 /en/ 迁移到 en 子域名:兼容数千条 Nginx 旧规则并避免二次 301

升级请求经过 EdgeOne,长时间运行的后台请求最终出现超时,数据库中还一度留下了 core_updater.lock

(17) 将 WordPress 后台迁移到独立 admin 子域名:绕过 EdgeOne,解决核心升级 524 超时

【图 1,后台发布新文章后,中文首页仍未显示新文章】

(18) WordPress 多域名架构暂停复盘:en、admin、W3TC 与多 CDN 的可维护性重新评估

图5:media、en 和 admin 尚未拆分时,EdgeOne 单日产生了 6.56GB 流量和 18.32 万次请求

(19) 将 media、en、admin 拆出 EdgeOne 后,我重新估算了网站每月的实际 CDN 成本

图6:英文文章通过 Cloudflare 的海外节点第二次测速结果

(20) 将 media、en、admin 拆出 EdgeOne 后,当前网站性能实测:BOCE、成都移动与 WebPageTest 对比

图13:EdgeOne 调整后的请求缓存状态

(21) WordPress 双 CDN 缓存实测:HTML TTL 统一为 12 小时后,EdgeOne 与 Cloudflare Hit 是否提升?

图3:EdgeOne 中标准文章 URL 与不同随机 Query String 均命中已有缓存

(22) 用 EdgeOne 与 Cloudflare 统一解决 WordPress 随机 Query String 缓存穿透:只优化 canonical 文章 URL

图 2:Cloudflare 明确返回 Invalid SSL certificate

(23) Cloudflare 526 排查实录:acme.sh 的 RSA / ECC 双证书自动续期,如何把英文站 SSL 覆盖坏了

图 2:EdgeOne 规则编辑界面,首页与 Sitemap 在同一条规则中分别设置 2 小时节点缓存 TTL。

(24) WordPress 发布新文章后首页仍是旧内容?EdgeOne 与 Cloudflare 将首页和 Sitemap 缓存缩短到 2 小时实测

前一段时间,为了提高 WordPress 的缓存命中率、减少页面回源带来的服务器压力,我逐步将 W3 Total Cache、EdgeOne 和 Cloudflare 的主要页面缓存生命周期统一调整到了 96 小时,也就是 4 天

此前我已经在《从 CPU 告警到双域名预缓存:W3 Total Cache、EdgeOne 与 Cloudflare 96 小时缓存优化实战》中记录过这套缓存策略:

不过 4 天长缓存运行以后,也出现了一个比较实际的问题:

新文章已经发布,但 CDN 中的首页可能仍然是旧内容。

普通文章发布以后通常不会频繁变化,4 天缓存并没有什么问题。

但首页和 Sitemap 不一样。

每次发布新文章后:

  • 首页文章列表会变化;
  • Sitemap 索引可能变化;
  • post-sitemap.xml 等子 Sitemap 也可能更新。

因此这一次,我没有重新降低整个网站的缓存时间,而是只针对这些高变化页面设置更短的 CDN 边缘缓存。

最终调整为:

页面CDN 边缘缓存时间
www 首页2 小时
www 公开 Yoast Sitemap2 小时
en 首页2 小时
en 公开 Yoast Sitemap2 小时
普通 HTML 页面继续 4 天
W3 Total Cache Page Cache继续 4 天

这样可以在保持大部分页面长期缓存的同时,把新文章发布后首页和 Sitemap 的最长旧缓存时间从 4 天缩短到约 2 小时。

一、为什么没有直接做“发布文章后自动清除 CDN”

理论上,更精确的方案是:

文章发布以后,由 WordPress 自动调用 EdgeOne 和 Cloudflare API,清除对应的首页与 Sitemap 缓存。

整个流程可以做成:

WordPress 发布文章 → 清理本地缓存 → 判断中文或英文 → 调用 CDN API → 精确 Purge 首页和 Sitemap。

这种方案能够让新文章几乎立即出现在 CDN 页面中。

但它也意味着需要继续维护:

  • WordPress 发布 Hook;
  • EdgeOne API;
  • Cloudflare API;
  • API Token;
  • 中英文域名判断;
  • Purge 失败处理;
  • 重试机制。

而我目前真正需要解决的,并不是:

新文章发布后必须几秒钟就在首页出现。

而是:

不能因为 4 天 CDN 缓存,让首页长期保持旧内容。

如果最多接受约 2 小时的更新延迟,那么单独给首页和 Sitemap 设置较短 TTL,会简单很多。

因此这一次没有重新启用 WordPress 后台已经停用的 Cloudflare 插件,也没有增加自动 Purge 代码。

二、为什么统一选择 2 小时

最开始我考虑过把首页和 Sitemap 设置为 1 小时。

不过为了让 EdgeOne 和 Cloudflare 两边的配置保持一致,最后统一选择:

2 小时

这样以后再看缓存策略时也比较容易理解:

  • 高变化入口:2 小时;
  • 普通 HTML:4 天。

不需要记忆两套不同的时间。

更重要的是,这次只缩短少数几个高变化 URL,并不会明显影响整个网站的缓存命中率。

三、Yoast Sitemap 不只有 sitemap_index.xml

网站目前使用 Yoast SEO。

打开中文站:

https://www.shuijingwanwq.com/sitemap_index.xml

可以看到当前 Sitemap Index 中包含多个子 Sitemap。

图 1:当前 Yoast SEO Sitemap Index,可以看到 post、page、category、post_tag、series 等多种 Sitemap。
图 1:当前 Yoast SEO Sitemap Index,可以看到 post、page、category、post_tag、series 等多种 Sitemap。

其中包括类似:

/post-sitemap.xml

/post-sitemap2.xml

/page-sitemap.xml

/category-sitemap.xml

/post_tag-sitemap.xml

/post_tag-sitemap10.xml

/series-sitemap.xml

/series_group-sitemap.xml

所以只给:

/sitemap_index.xml

设置 2 小时还不够。

真正发布文章以后,最直接发生变化的往往反而是:

/post-sitemap.xml

因此这次需要同时覆盖 Sitemap Index 和各个公开子 Sitemap。

四、w3tc-preload-sitemap.xml 不纳入这次规则

网站还有一个特殊文件:

/w3tc-preload-sitemap.xml

这是此前为了 W3 Total Cache Cache Preload 单独生成的联合 Sitemap。

不过它的用途与搜索引擎公开访问的 Yoast Sitemap 不一样。

当前实现中,W3TC Preload 会通过自己的流程读取源站 Sitemap,因此这次需要解决的 CDN 内容更新问题,并不涉及这个文件。

所以:

/w3tc-preload-sitemap.xml 不纳入“公开 Sitemap 2 小时缓存”范围。

这也意味着在 EdgeOne 规则中,需要明确把它排除。


五、EdgeOne:一条规则同时处理首页与 Sitemap

中文站:

www.shuijingwanwq.com

目前通过 EdgeOne 提供 CDN。

为了减少规则数量,我没有分别创建:

“首页缓存 2 小时”

和:

“Sitemap 缓存 2 小时”

而是创建了一条:

首页与 Sitemap 缓存 2 小时

最外层首先限定 Host:

www.shuijingwanwq.com

下面再创建两个同级 IF2。

第一个处理首页:

URL Path = /

第二个处理公开 Sitemap。

图 2:EdgeOne 规则编辑界面,首页与 Sitemap 在同一条规则中分别设置 2 小时节点缓存 TTL。
图 2:EdgeOne 规则编辑界面,首页与 Sitemap 在同一条规则中分别设置 2 小时节点缓存 TTL。

首页分支非常简单:

URL path 等于 /

操作:

  • 节点缓存 TTL;
  • 自定义时间;
  • 2 小时;
  • 强制缓存关闭。

Sitemap 分支使用正则:

Plaintext
^/(sitemap_index|[^/]+-sitemap[0-9]*)\.xml$

并增加:

URL Path 不等于 /w3tc-preload-sitemap.xml

这个正则能够覆盖:

  • /sitemap_index.xml
  • /post-sitemap.xml
  • /post-sitemap2.xml
  • /page-sitemap.xml
  • /category-sitemap.xml
  • /post_tag-sitemap.xml
  • /post_tag-sitemap10.xml
  • /series-sitemap.xml
  • /series_group-sitemap.xml

同时又不会让 w3tc-preload-sitemap.xml 最终进入 2 小时缓存。

保存以后,规则摘要如下。

图 3:EdgeOne 最终规则:首页和公开 Sitemap 都设置为 2 小时,w3tc-preload-sitemap.xml 被单独排除。
图 3:EdgeOne 最终规则:首页和公开 Sitemap 都设置为 2 小时,w3tc-preload-sitemap.xml 被单独排除。

六、EdgeOne 规则要放在原来的 4 天 HTML 规则之后

原来的:

HTML页面缓存(SEO安全)

仍然保留。

它负责普通 HTML 的长期缓存。

新增的:

首页与 Sitemap 缓存 2 小时

放在规则列表更靠后的位置。

图 4:EdgeOne 规则列表,新建的“首页与 Sitemap 缓存 2 小时”位于现有通用缓存规则之后。
图 4:EdgeOne 规则列表,新建的“首页与 Sitemap 缓存 2 小时”位于现有通用缓存规则之后。

因此普通文章不会因为这次调整全部降到 2 小时。

实际结果是:

普通 HTML → 继续 4 天
首页 → 2 小时
公开 Sitemap → 2 小时

这才是这次调整真正想达到的效果。


七、Cloudflare 当前已经有多条 Cache Rules

英文站:

en.shuijingwanwq.com

目前通过 Cloudflare。

开始修改以前,我先检查了现有 Cache Rules。

图 5:Cloudflare 调整前已有多条 WordPress 缓存和绕过规则。
图 5:Cloudflare 调整前已有多条 WordPress 缓存和绕过规则。

其中比较关键的是:

  • HTML 页面缓存(SEO安全)
  • WordPress 个性化 Cookie 绕过缓存

因此这一次也没有拆成多条规则,而是只新增:

首页与 Sitemap 缓存 2 小时

这样可以尽量减少规则数量,也方便以后维护。

八、Cloudflare 使用 Host + URI Path 匹配

Cloudflare 这边最终使用的表达式为:

Plaintext
(http.host eq "en.shuijingwanwq.com" and (
  http.request.uri.path eq "/"
  or http.request.uri.path eq "/sitemap_index.xml"
  or http.request.uri.path wildcard "/*-sitemap*.xml"
))

这里分别处理:

首页:

/

Sitemap Index:

/sitemap_index.xml

其他子 Sitemap:

/*-sitemap*.xml

由于这条规则本身已经限定:

en.shuijingwanwq.com

w3tc-preload-sitemap.xml 位于中文 www 域名,因此 Cloudflare 这一侧不需要再专门排除它。

边缘 TTL 设置为:

忽略缓存控制标头,使用此 TTL

时间:

2 小时

图 6:Cloudflare Cache Rule 使用自定义表达式匹配英文首页和 Sitemap,并将 Edge TTL 设置为 2 小时。
图 6:Cloudflare Cache Rule 使用自定义表达式匹配英文首页和 Sitemap,并将 Edge TTL 设置为 2 小时。

浏览器 TTL 没有在这一步修改。

这次调整的重点只是:

Cloudflare 边缘节点缓存生命周期。


九、Cloudflare 的规则顺序同样很重要

新增规则以后,最终相关顺序变成:

  1. HTML 页面缓存(SEO安全)
  2. 首页与 Sitemap 缓存 2 小时
  3. WordPress 个性化 Cookie 绕过缓存
图 7:Cloudflare 最终规则顺序,2 小时规则位于通用 HTML 缓存之后、个性化 Cookie 绕过规则之前。
图 7:Cloudflare 最终规则顺序,2 小时规则位于通用 HTML 缓存之后、个性化 Cookie 绕过规则之前。

这个位置很重要。

普通访客访问首页时:

通用 HTML 规则先匹配,再由第 7 条把 Edge TTL 调整成 2 小时。

但如果请求带有登录或其他个性化 Cookie,最后仍然会命中第 8 条:

WordPress 个性化 Cookie 绕过缓存

因此不会因为增加了首页缓存规则,就把登录用户的个性化页面重新缓存起来。


十、新规则发布以后,先进行一次 URL Purge

仅仅修改 TTL,并不能保证节点中已经存在的旧缓存立即失效。

例如首页此前已经按照 4 天策略建立缓存,新规则发布以后,那份旧缓存仍然可能继续存在。

因此 EdgeOne 和 Cloudflare 两边配置完成后,我都做了一次自定义 URL 清除。

主要处理:

  • 首页;
  • /sitemap_index.xml
  • /post-sitemap.xml

没有执行全站 Purge。

这次清除的目的只是:

让已有的 4 天旧缓存失效,使新的 2 小时规则立即开始接管。

正常运行以后,并不需要每次发布文章都手工清理。


十一、第一次测试时发现代理会干扰 CDN 判断

最开始测试 EdgeOne 时,我连续访问:

  • 首页;
  • sitemap_index.xml
  • post-sitemap.xml
  • 一个普通文章页。

结果出现了:

  • 请求超时;
  • 多次 MISS;
  • 普通文章也出现 MISS。

当时的 curl 输出还包含:

HTTP/1.1 200 Connection established

后来确认,本地请求经过了代理。

为了避免代理出口和 CDN 节点变化干扰测试,后面统一增加:

Bash
--noproxy '*'

例如:

Bash
curl -4 --noproxy '*' -sS \
    --connect-timeout 10 \
    --max-time 60 \
    -o /dev/null \
    -D - \
    "https://www.shuijingwanwq.com/"

绕过代理以后,EdgeOne 首页很快得到:

第一次:

MISS

随后:

HIT

并且:

Age: 5

后面继续增长。

这说明首页已经成功进入 EdgeOne 节点缓存。


十二、EdgeOne Sitemap 与普通文章验证

接下来分别测试:

/sitemap_index.xml

/post-sitemap.xml

以及一个普通文章页。

结果:

sitemap_index.xml

第一次:

MISS

第二次:

MISS

第三次:

HIT

post-sitemap.xml

第一次:

MISS

随后:

HIT

HIT

这说明 Sitemap 确实能够正常进入 EdgeOne 缓存,同时也证明我们设置的匹配范围覆盖到了 /post-sitemap.xml

而普通文章页则连续返回:

HIT

并且 Age:

221 → 226 → 231

说明新增规则没有破坏普通文章原来的长期缓存。


十三、Cloudflare 第一次验证同样成功

Cloudflare 清除缓存以后,对英文首页进行访问:

第一次:

CF-Cache-Status: MISS

随后:

HIT

Age: 3

再次:

HIT

Age: 6

说明首页重新进入了 Cloudflare 边缘缓存。

/post-sitemap.xml 也表现为:

MISS → HIT → HIT

因此:

/*-sitemap*.xml

确实能够匹配当前 Yoast 子 Sitemap。

测试普通英文文章时还出现了一组很有意思的数据:

LAX 节点:

HIT

Age: 28182

下一次请求到了 LAS:

MISS

随后又回到 LAX:

HIT

Age: 28190

这也提醒我:

CDN 的缓存不是整个网络共享一个统一 Age,而是分布在不同边缘节点中。

所以看到一次 MISS,不能直接判断缓存规则失效,还需要结合请求实际落到哪个 CDN 节点。


十四、MISS → HIT 还不能证明 TTL 真的是 2 小时

完成上述验证以后,还有一个问题:

我们只是证明缓存能够正常建立,但怎么知道 TTL 确实已经从 4 天变成了 2 小时?

例如:

MISS → HIT → HIT

无论 TTL 是:

  • 2 小时;
  • 4 小时;
  • 4 天;

刚建立缓存时都有可能出现相同结果。

因此我没有立即结束测试,而是等了两个多小时以后再次检查。


十五、两个多小时后,EdgeOne 首页重新 MISS

EdgeOne 首页最初重新建立缓存大约是在 18:45 左右。

到了 21:12,再次测试。

第一次:

EO-Cache-Status: MISS

随后:

HIT

Age: 12

再次:

HIT

Age: 26

这表示此前已经存在的那份首页缓存,在两个多小时以后已经不再继续直接使用。

新的请求重新建立缓存以后,Age 又从很小的数值开始增长。

单凭一次 MISS,不能绝对排除节点变化、缓存淘汰等其他因素。

不过结合:

  • EdgeOne 中明确配置为 2 小时;
  • 配置后已经确认首页可以 HIT;
  • 等待时间超过 2 小时;
  • 再次访问变为 MISS;
  • 随后立刻 HIT;
  • Age 从十几秒重新开始;

实际行为已经与 2 小时节点缓存 TTL 完全吻合。


十六、Cloudflare 的 2 小时过期证据更加直接

Cloudflare 英文首页大约在 19:02 左右重新建立缓存。

到了 21:13 再次测试。

第一次返回:

CF-Cache-Status: EXPIRED

节点:

LAX

第二次:

CF-Cache-Status: HIT

Age: 4

仍然是:

LAX

第三次:

HIT

Age: 7

同样还是:

LAX

也就是说,在同一个 Cloudflare 节点上完整观察到了:

缓存存在 → TTL 到期 → EXPIRED → 重新获取 → HIT → Age 重新开始

因此 Cloudflare 这边可以比较明确地确认:

2 小时 Edge TTL 已经实际生效。


十七、为什么 Cloudflare 仍然返回 max-age=14400

Cloudflare 的响应中还有一个容易让人误解的地方。

即使 Edge TTL 已经设置为 2 小时,响应仍然显示:

cache-control: max-age=14400

14400 秒等于:

4 小时

但两个多小时以后,Cloudflare 已经出现:

CF-Cache-Status: EXPIRED

这并不矛盾。

因为这一次修改的是:

Cloudflare Edge TTL

而响应里的:

Cache-Control: max-age=14400

是客户端能够看到的缓存控制信息。

也就是说,目前可以同时存在:

Cloudflare Edge:2 小时
客户端 Cache-Control:4 小时

而且实际 EXPIRED 结果已经证明 Cloudflare 边缘节点没有继续按照 4 小时甚至 4 天缓存首页。

浏览器 TTL 是否也需要从 4 小时调整到 2 小时,是另外一个问题。

这次我暂时没有继续扩大调整范围。


十八、最终缓存结构

经过这次调整以后,目前主要策略可以概括为:

范围缓存时间
W3 Total Cache Page Cache4 天
EdgeOne 普通 HTML4 天
EdgeOne 首页2 小时
EdgeOne 公开 Yoast Sitemap2 小时
Cloudflare 普通 HTML4 天
Cloudflare 首页2 小时
Cloudflare 公开 Yoast Sitemap2 小时

w3tc-preload-sitemap.xml 不参与这次公开 Sitemap CDN TTL 调整。

Cloudflare WordPress 插件继续保持停用。

也没有增加 WordPress Hook 或 CDN API 自动 Purge。


十九、这次优化后的取舍

之前把缓存时间提升到 4 天,本身并没有错。

它解决的是:

普通页面反复回源、缓存生命周期过短、缓存命中率偏低的问题。

而这一次解决的是另一个问题:

首页和 Sitemap 属于高变化页面,不应该和普通文章完全使用相同的缓存生命周期。

因此最终并不是在“2 小时”和“4 天”之间二选一,而是按页面性质区分:

而是按页面性质区分:

稳定页面使用 4 天长缓存,高变化入口使用 2 小时短缓存。

这样发布新文章以后,即使完全不做主动 Purge,CDN 边缘层面的旧首页和 Sitemap 最多也只需要等待约 2 小时。

与此同时,大量普通文章仍然可以继续享受 4 天缓存。

相比为 EdgeOne 和 Cloudflare 分别实现文章发布后的自动清理,这套方案简单很多,后续维护成本也低。

而从实际等待两个多小时后的测试结果来看:

  • EdgeOne 出现 MISS → HIT,Age 重新开始;
  • Cloudflare 明确出现 EXPIRED → HIT,Age 从 4 秒重新开始。

因此目前我准备继续保留这套配置。

以后如果实际需求变成:

文章发布以后,首页必须立即出现新内容。

再进一步引入 CDN API 精确 Purge。

但对于目前的网站来说,首页和 Sitemap 2 小时、普通页面 4 天,已经是一个更适合当前访问规模和维护成本的折中方案。

Cloudflare 526 排查实录:acme.sh 的 RSA / ECC 双证书自动续期,如何把英文站 SSL 覆盖坏了

Linux 服务器运维、部署与线上故障排查

如果你的网站或后端服务部署在 Linux 服务器上,遇到访问异常、Nginx 配置问题、MySQL / Redis 异常、Docker 服务不可用、磁盘占满、CPU / 内存过高等问题,可以联系我做一次远程排查。

适合以下场景:
✅ 网站打不开或访问不稳定
✅ Nginx / PHP-FPM 配置异常
✅ MySQL / Redis 性能或连接问题
✅ Docker 服务部署与维护
✅ 服务器迁移与环境配置
✅ CPU / 内存 / 磁盘异常排查

服务内容:
✅ Linux 环境检查
✅ 网站部署与迁移
✅ Nginx / PHP-FPM / MySQL / Redis 排查
✅ Docker 配置与维护
✅ 服务器性能分析
✅ 长期远程运维支持

如需咨询,请联系我,并注明:Linux 运维咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理