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

补上日期归档分页测试:EdgeOne 与 Cloudflare Query String 归一化再次验证

【图 3:Cloudflare 四次请求全部 HIT,age 持续增长,但四份原始 HTML SHA-256 全部不同】

作者:

,

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 小时实测

图1:EdgeOne 7 月 30 日 L7 请求量异常上涨

(25) EdgeOne 请求数突然暴涨:从 177 万次异常请求定位到百万级 PHP 文件扫描

图 3:EdgeOne 规则保存后的完整结构。文章详情页与公开列表页共用同一条规则。

(26) 从 EdgeOne 524 到 Query String 归一化:WordPress 文章与公开列表页 CDN 缓存优化实战

【图 3:Cloudflare 四次请求全部 HIT,age 持续增长,但四份原始 HTML SHA-256 全部不同】

(27) 补上日期归档分页测试:EdgeOne 与 Cloudflare Query String 归一化再次验证

前一篇文章《从 EdgeOne 524 到 Query String 归一化》中,我记录了 WordPress 中文站在 EdgeOne 下出现 524 故障之后,对 Query String 缓存策略进行排查、调整和验证的过程。(水晶湾网址)

当时已经测试了多种文章页、列表页和归档分页,但还留下了一个没有真正覆盖到的场景:

Plaintext
/YYYY/MM/DD/page/N/

也就是日期归档分页

原因很简单:测试时没有找到一个真实存在、已经产生分页的日期归档,所以只能暂时跳过。

到了 2026 年 8 月 15 日,站点当天发布的文章数量已经足够多,终于产生了真实可访问的第 3 页:

Plaintext
中文站:
https://www.shuijingwanwq.com/2026/08/15/page/3/

英文站:
https://en.shuijingwanwq.com/2026/08/15/page/3/

于是我决定把这个遗漏的测试项补上。

原本以为这只是一次很简单的补测,结果英文站 Cloudflare 又出现了一个有意思的现象:

Cloudflare 明明一直命中缓存,但每次返回的完整 HTML SHA-256 却不一样。

继续对比页面之后,最终发现缓存本身没有问题,真正造成哈希变化的是 Cloudflare 对页面中邮箱地址进行的动态混淆。

这次补测因此除了补齐日期归档分页,也顺便修正了一个以后进行 CDN 缓存测试时很重要的判断方法。

日期归档第 3 页终于出现

这次能够实际测试的中文页面是:

Plaintext
https://www.shuijingwanwq.com/2026/08/15/page/3/

浏览器中已经可以看到:

Plaintext
首页 / 2026 / 8月 / 15 / 第3页

页面标题则是:

Plaintext
日期: 2026年8月15日

下面继续列出当天较早发布的文章。

【图 1:2026 年 8 月 15 日日期归档第 3 页,证明 /YYYY/MM/DD/page/N/ 类型的真实页面已经出现】
【图 1:2026 年 8 月 15 日日期归档第 3 页,证明 /YYYY/MM/DD/page/N/ 类型的真实页面已经出现】

这正是上一篇测试中缺少的 URL 类型。

之前虽然已经验证过其他归档页和分页,但从 CDN 缓存规则的角度看:

Plaintext
/2026/08/15/

与:

Plaintext
/2026/08/15/page/3/

毕竟是两个不同的路径。

既然现在已经有真实页面,就没有必要继续依赖推测,可以直接进行实际请求验证。

中文站 EdgeOne:随机 Query String 直接命中已有缓存

中文站仍然沿用之前的测试思路。

首先请求不带参数的正常页面:

Plaintext
https://www.shuijingwanwq.com/2026/08/15/page/3/

然后生成一个带当前时间戳、此前没有访问过的随机 Query String:

Plaintext
?swq_qs_test=date-page-1786844745

形成:

Plaintext
https://www.shuijingwanwq.com/2026/08/15/page/3/?swq_qs_test=date-page-1786844745

测试结果很直接:

Plaintext
========== EdgeOne 日期归档分页 ==========

HTTP/2 200
eo-cache-status: MISS

--- RANDOM QUERY STRING ---

HTTP/2 200
eo-cache-status: HIT

正常 URL 第一次请求为:

Plaintext
MISS

而紧接着请求刚刚生成的随机 Query String,却直接得到:

Plaintext
HIT

进一步比较两份 HTML:

Plaintext
b032f39e333db0afe4952b22effcf9955ed1bd4a09076c6fa6a792bf9dc40a39  clean
b032f39e333db0afe4952b22effcf9955ed1bd4a09076c6fa6a792bf9dc40a39  dirty

最终:

Plaintext
same_body=yes
【图 2:EdgeOne 日期归档分页测试,Clean 为 MISS,随机 Query String 为 HIT,两份 HTML SHA-256 完全一致】
【图 2:EdgeOne 日期归档分页测试,Clean 为 MISS,随机 Query String 为 HIT,两份 HTML SHA-256 完全一致】

这个结果已经足以说明:

EdgeOne 没有因为这个无关 Query String 创建新的页面缓存,日期归档分页同样能够按照当前规则进行 Query String 归一化。

因此中文站这一项可以直接判定通过。

英文站 Cloudflare:随机参数同样第一次就是 HIT

然后测试英文站:

Plaintext
https://en.shuijingwanwq.com/2026/08/15/page/3/

同样先访问正常页面,再生成一个新的随机参数:

Plaintext
?swq_cf_qs_test=date-page-1786844818

第一次测试时得到:

Plaintext
CLEAN:

cf-cache-status: HIT
age: 254

随后请求刚刚生成的随机 Query String:

Plaintext
DIRTY:

cf-cache-status: HIT
age: 255

这个现象本身已经很有价值。

因为这个随机参数刚刚才生成,此前并不存在对应的访问历史。

如果 Cloudflare 把完整 Query String 当成独立缓存键,那么第一次访问这个随机 URL,通常应该更容易看到新的缓存对象。

但实际结果却是:

Plaintext
HIT

而且缓存年龄直接从:

Plaintext
254

增长到了:

Plaintext
255

从这一点来看,随机 Query String 很明显正在继续使用已有缓存。

但完整 HTML SHA-256 居然不同

问题出现在正文比较上。

第一次测试得到:

Plaintext
a82d0be563742050ebb8e0595c6182a9a657d0f3d9da831da0081e9d74f1b7b5  clean

e595a892523e343bf52f093cdcc98951e1cc1cb9b770d64c2b4bbe18cba602f8  dirty

same_body=no

也就是说:

Plaintext
Clean SHA-256 != Dirty SHA-256

如果按照之前比较直接的判断方式,很容易得到:

Plaintext
随机 Query String
→ 页面正文发生变化
→ 可能没有真正实现缓存归一化

但这个结论和缓存头又明显存在矛盾。

因为随机参数第一次访问已经是:

Plaintext
HIT

而且:

Plaintext
age

仍然沿着原来的缓存年龄增长。

所以这里不能直接根据整页 SHA-256 下结论。

先检查相同 URL 自己是否稳定

为了排除 Query String 本身的影响,我又做了一组对照测试:

Plaintext
Clean 1
Clean 2
Dirty 1
Dirty 2

也就是:

  • 相同 Clean URL 连续访问两次;
  • 相同 Dirty URL 连续访问两次。

缓存结果如下:

Plaintext
age: 341
cf-cache-status: HIT

age: 342
cf-cache-status: HIT

age: 344
cf-cache-status: HIT

age: 345
cf-cache-status: HIT

四次请求全部:

Plaintext
HIT

缓存年龄也持续增长:

Plaintext
341
342
344
345

没有出现 Dirty 请求重新建立缓存的迹象。

但下面的原始 SHA-256 却全部不同。

【图 3:Cloudflare 四次请求全部 HIT,age 持续增长,但四份原始 HTML SHA-256 全部不同】
【图 3:Cloudflare 四次请求全部 HIT,age 持续增长,但四份原始 HTML SHA-256 全部不同】

这一步实际上已经说明:

问题不可能简单归因于 Query String。

因为就连:

Plaintext
Clean 1

和:

Plaintext
Clean 2

这两个完全相同的 URL,返回的 HTML SHA-256 也不同。

比较结果是:

Plaintext
clean1_vs_clean2=different
dirty1_vs_dirty2=different
clean_vs_dirty=different

这意味着 Cloudflare 返回 HTML 的过程中,还有某个动态内容在发生变化。

直接比较 HTML,终于找到唯一差异

继续对:

Plaintext
Clean 1

和:

Plaintext
Clean 2

进行逐行比较以后,终于找到了真正的变化。

第一次响应中,页面底部 Mail 社交链接的一部分是:

HTML
href="/cdn-cgi/l/email-protection#0e7d667b6764676069796f60797f4e69636f6762206d6163"

第二次则变成:

HTML
href="/cdn-cgi/l/email-protection#1a69726f737073747d6d7b746d6b5a7d777b737634797577"

其他页面内容并没有发生变化。

差异集中在:

Plaintext
/cdn-cgi/l/email-protection#...

这里。

到这一步,问题就比较清楚了。

页面底部存在邮件链接,而经过 Cloudflare 返回以后,邮箱地址被改写成了:

Plaintext
/cdn-cgi/l/email-protection#...

形式。

这个保护值会变化,因此即使:

  • WordPress 页面内容没有变化;
  • 文章列表没有变化;
  • 分页没有变化;
  • Cloudflare 命中的还是已有缓存;

最终发送到客户端的 HTML 仍然可能出现几个字节的不同。

而 SHA-256 对任何一个字节变化都会敏感。

所以此前:

Plaintext
same_body=no

并不能说明 Cloudflare 缓存出现了问题。

将 Cloudflare 动态邮箱保护值归一化

为了最终确认,我又做了一次处理。

在计算 SHA-256 之前,只把:

Plaintext
/cdn-cgi/l/email-protection#后面的动态值

统一替换为:

Plaintext
/cdn-cgi/l/email-protection#NORMALIZED

其他 HTML 一个字节也不动。

然后重新计算:

Plaintext
Clean 1
Clean 2
Dirty 1
Dirty 2

四份页面的 SHA-256。

最终结果:

Plaintext
clean1  7eb9c5d221cde81de8a9824f433e5fff360d70940ee01afeed97e7899ef854bf

clean2  7eb9c5d221cde81de8a9824f433e5fff360d70940ee01afeed97e7899ef854bf

dirty1  7eb9c5d221cde81de8a9824f433e5fff360d70940ee01afeed97e7899ef854bf

dirty2  7eb9c5d221cde81de8a9824f433e5fff360d70940ee01afeed97e7899ef854bf

四份完全一致。

最终比较:

Plaintext
clean1_vs_clean2 = same
dirty1_vs_dirty2 = same
clean_vs_dirty   = same
【图 4:归一化 Cloudflare 邮箱保护值以后,Clean 与 Dirty 四份 HTML SHA-256 完全一致】

到这里,整个问题就完全闭环了。

英文站 Cloudflare 同样通过

综合全部证据,英文站的日期归档分页最终同样可以判定通过。

测试 URL:

Plaintext
https://en.shuijingwanwq.com/2026/08/15/page/3/

随机 Query String 第一次访问:

Plaintext
cf-cache-status: HIT

缓存年龄连续增长:

Plaintext
341
342
344
345

说明随机 Query String 没有明显创建新的独立缓存对象。

最初出现的:

Plaintext
Clean SHA-256 != Dirty SHA-256

进一步证明不是 Query String 引起。

因为完全相同的:

Plaintext
Clean 1
Clean 2

原始 HTML 同样不同。

最后将:

Plaintext
/cdn-cgi/l/email-protection#...

这个 Cloudflare 动态字段归一化以后:

Plaintext
Clean 1 = Clean 2 = Dirty 1 = Dirty 2

因此最终结论是:

Cloudflare 对日期归档分页的 Query String 归一化同样正常。

两个 CDN 的最终测试结果

这次补测可以简单整理为下面两组结果。

中文站 EdgeOne:

Plaintext
URL:
/2026/08/15/page/3/

HTTP:
200

Clean:
MISS

随机 Query String:
HIT

原始 HTML:
SHA-256 一致

same_body:
yes

结果:
通过

英文站 Cloudflare:

Plaintext
URL:
/2026/08/15/page/3/

HTTP:
200

Clean:
HIT

随机 Query String 首次访问:
HIT

缓存 age:
连续增长

原始 HTML:
存在动态差异

差异来源:
/cdn-cgi/l/email-protection#...

归一化 Cloudflare 动态字段后:
Clean 1 = Clean 2 = Dirty 1 = Dirty 2

结果:
通过

至此,上一篇文章中没有覆盖到的:

Plaintext
/YYYY/MM/DD/page/N/

日期归档分页已经正式补测完成。

这次真正值得记录的是测试方法的变化

最开始,我只是想补一个漏掉的日期归档分页。

但这次最有价值的收获,反而不是日期分页本身,而是进一步确认:

完整 HTML 的原始 SHA-256,不能在所有 CDN 场景中被当成页面缓存一致性的绝对判据。

中文站 EdgeOne 这次非常简单:

Plaintext
Clean SHA-256 = Dirty SHA-256

因此可以直接判断内容一致。

但是英文站经过 Cloudflare 以后,情况不同。

Cloudflare还可能在缓存对象返回给浏览器的过程中,对某些 HTML 内容进行动态处理。

这次已经实际遇到:

Plaintext
/cdn-cgi/l/email-protection#...

每次发生变化。

这种差异并不代表:

  • WordPress 生成了不同页面;
  • Query String 导致了不同页面;
  • Cloudflare 建立了不同缓存;
  • 缓存规则失效。

它只是说明:

客户端最终拿到的 HTML,还可能包含 CDN 自己产生的动态字段。

以后如何测试 Query String 缓存

经过这次验证,以后再测试类似问题,我会把判断顺序调整一下。

首先检查:

Plaintext
HTTP 状态

确认页面本身能够正常访问。

然后检查 CDN 的缓存状态,例如:

Plaintext
eo-cache-status

或者:

Plaintext
cf-cache-status

接着观察随机 Query String 第一次请求究竟是:

Plaintext
MISS

还是:

Plaintext
HIT

对于 Cloudflare,还可以继续结合:

Plaintext
age

判断它是不是沿用已有缓存对象。

如果还需要进行正文级别确认,再比较 HTML。

但如果原始 SHA-256 不一致,不再立即判定:

Plaintext
缓存失败

而是先检查:

Plaintext
相同 Clean URL 连续请求是否也不同

如果相同 URL 自己都不稳定,那么就继续定位动态字段。

最后,把明确属于 CDN 自身响应处理、与业务页面内容无关的动态字段归一化以后,再进行真正的正文哈希比较。

相比单纯使用:

Plaintext
same_body=yes/no

这种方法明显更加可靠。

总结

上一篇《从 EdgeOne 524 到 Query String 归一化》留下的日期归档分页测试缺口,这次终于补上了。

真实测试页面为:

Plaintext
/2026/08/15/page/3/

中文站 EdgeOne 中:

Plaintext
Clean:MISS
Dirty:HIT
same_body=yes

日期归档分页 Query String 归一化工作正常。

英文站 Cloudflare 中,随机 Query String 第一次访问同样直接:

Plaintext
HIT

缓存年龄持续增长。

虽然原始 HTML SHA-256 一度全部不同,但最终通过逐行比较确认,唯一差异来自:

Plaintext
/cdn-cgi/l/email-protection#...

将这一 Cloudflare 动态字段归一化以后:

Plaintext
Clean 1
Clean 2
Dirty 1
Dirty 2

四份 HTML 的 SHA-256 完全一致。

因此最终可以确认:

EdgeOne 与 Cloudflare 对 WordPress 日期归档分页的 Query String 归一化均工作正常。

而这次测试也进一步完善了后续 CDN 验证的方法:

先看缓存状态和缓存年龄,再判断随机参数是否命中已有缓存;需要比较正文时,还要先排除 CDN 自己的动态响应改写,不能仅凭整页原始 SHA-256 不同就判断缓存异常。

从 EdgeOne 524 到 Query String 归一化:WordPress 文章与公开列表页 CDN 缓存优化实战

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 来减少垃圾评论。了解你的评论数据如何被处理