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

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

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

作者:

,

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 缓存优化实战

此前,我已经针对 WordPress 文章详情页做过一次 Query String 归一化处理。

当文章详情页带有 ampnonamp、随机测试参数或其他无意义查询参数时,CDN 不再为每一种参数组合分别建立缓存,而是统一复用 canonical URL 对应的缓存。同时,在缓存未命中并回源时,查询参数也不会继续传给 WordPress。

此前的处理过程记录在这篇文章中:

通过 EdgeOne 与 Cloudflare 统一 WordPress 文章 Query String

不过,后来发生的一次 EdgeOne 524 故障让我发现,仅处理文章详情页还不够。

大量分类页、标签页、系列页、日期归档页和分页地址,同样会被爬虫附加各种查询参数。如果这些参数全部参与 CDN 缓存 Key,就会制造大量缓存碎片,并反复触发 WordPress 动态回源。

这一次,我把相同的 Query String 归一化方案扩展到了 WordPress 的公开列表页面,并分别在中文站 EdgeOne 和英文站 Cloudflare 上完成配置与验证。

一、问题是怎样暴露出来的

2026 年 8 月 2 日晚间,中文站一度出现大量 EdgeOne 524。

故障窗口内,EdgeOne 统计到了 151 次 524:

  • 缓存 MISS:147 次
  • 动态请求:4 次
  • 缓存 HIT:0 次

这些请求并不集中在某一篇文章,而是分散在首页、分类页、标签页、日期归档和分页地址中。

源站 Nginx 日志中同时出现了大量 499。请求中包含首页、分类页以及带有 query-62-pageampnonamp 等参数的地址。

PHP-FPM 当时使用以下配置:

  • ECS:1 核 CPU
  • pm = ondemand
  • pm.max_children = 7
  • request_slowlog_timeout = 3s
  • request_terminate_timeout = 600s

慢日志显示,在故障期间,7 个 PHP-FPM 子进程曾同时卡在 index.php 中。随后日志中又出现:

Plaintext
server reached pm.max_children setting (7)

由于服务器只有 1 核 CPU,继续提高 pm.max_children 并不是一个合理方向。

即使增加 PHP 进程数量,也只是让更多进程争抢同一个 CPU。真正需要减少的是:

同一个页面因为不同 Query String 被反复当作不同资源,导致 CDN 缓存 MISS,并同时回源执行 WordPress。

二、为什么查询参数会放大源站压力

下面这些 URL 在 WordPress 中实际上可能返回完全相同的内容:

Plaintext
https://www.shuijingwanwq.com/tag/cache/
https://www.shuijingwanwq.com/tag/cache/?amp=1
https://www.shuijingwanwq.com/tag/cache/?nonamp=1
https://www.shuijingwanwq.com/tag/cache/?query-62-page=43
https://www.shuijingwanwq.com/tag/cache/?random=value

但如果 CDN 默认将完整 Query String 纳入缓存 Key,它们就会被视为多个不同的缓存对象。

每一种新参数组合首次出现时,都可能触发一次源站回源。

当爬虫同时访问大量分类、标签、分页和归档页面时,这些缓存碎片就可能在短时间内占满 PHP-FPM 的全部进程。

因此,这次优化采用两层处理:

  1. Query String 不参与 CDN 缓存 Key;
  2. 缓存 MISS 回源时,直接删除 Query String。

第一层避免缓存碎片,第二层避免无意义参数继续传入 WordPress。

三、需要覆盖哪些公开列表页面

我先整理了中文站当前真实存在的列表页面:

Plaintext
https://www.shuijingwanwq.com/
https://www.shuijingwanwq.com/page/4/

https://www.shuijingwanwq.com/category/program-development/
https://www.shuijingwanwq.com/category/program-development/page/2/

https://www.shuijingwanwq.com/tag/cache/
https://www.shuijingwanwq.com/tag/cache/page/2/

https://www.shuijingwanwq.com/series-category/blog-management-practices/

https://www.shuijingwanwq.com/series/wordpress-cdn-global-acceleration-practice/
https://www.shuijingwanwq.com/series/wordpress-cdn-global-acceleration-practice/page/3/

https://www.shuijingwanwq.com/2026/
https://www.shuijingwanwq.com/2026/page/32/

https://www.shuijingwanwq.com/2026/07/
https://www.shuijingwanwq.com/2026/07/page/3/

https://www.shuijingwanwq.com/2026/07/30/

规则还需要兼容未来可能出现的分页:

Plaintext
/series-category/blog-management-practices/page/2/
/2026/07/30/page/2/

作者归档没有纳入范围。

本站是单作者博客,并且已经在 Yoast SEO 中关闭作者归档,因此 /author/.../ 不属于当前有效的公开列表页面。

只处理带结尾斜杠的 canonical URL

规则只匹配结尾带 / 的地址。

没有结尾斜杠的地址,例如:

Plaintext
/tag/cache
/category/program-development

会先由 WordPress 或现有规范化逻辑 301 跳转到:

Plaintext
/tag/cache/
/category/program-development/

随后再由 CDN 规则处理。

这与此前文章详情页的处理方式保持一致。

四、搜索页面必须保留 Query String

不能简单地对首页和所有 /page/数字/ 地址删除查询参数。

WordPress 搜索页依赖 s 参数:

Plaintext
https://www.shuijingwanwq.com/?s=autopoly
https://www.shuijingwanwq.com/page/2/?s=autopoly

搜索分页的路径本身也是 /page/2/

如果只根据 URL Path 判断,搜索分页就可能被误认为普通首页分页,随后删除 s=autopoly,最终返回普通文章列表。

因此,列表页分支必须额外要求:

Plaintext
查询参数 s 不存在

我还同时排除了列表页面中的 WordPress 预览参数:

Plaintext
preview
preview_id
preview_nonce

五、EdgeOne 中文站配置

我没有为文章详情页和公开列表页分别创建两条规则,而是把它们合并到同一条规则中。

规则名称为:

Plaintext
www 文章与公开列表页 Query String 归一化

最外层条件只有:

Plaintext
HOST 等于 www.shuijingwanwq.com

配置过程中遇到的一个限制

最初,我还在最外层加入了:

Plaintext
请求方法等于 GET、HEAD

但加入请求方法条件后,EdgeOne 界面不再允许添加“自定义 Cache Key”操作。

因此,最终删除了请求方法条件,只保留 HOST 条件,再在内部使用文章详情页和公开列表页两个分支。

六、EdgeOne 文章详情页分支

文章详情页继续使用此前已经验证过的正则:

Plaintext
^/[0-9]{4}/[0-9]{2}/[0-9]{2}/[0-9]+/$

例如:

Plaintext
/2026/07/27/20445/

该分支执行两项操作:

  • 自定义 Cache Key → 查询字符串 → 全部忽略
  • 回源请求参数设置 → 查询字符串 → 全部忽略
图 1:EdgeOne 文章详情页分支,同时忽略缓存 Key 和回源请求中的查询字符串。
图 1:EdgeOne 文章详情页分支,同时忽略缓存 Key 和回源请求中的查询字符串。

这里需要同时配置两项操作。

只忽略 Cache Key,可以避免不同参数生成不同缓存对象;但缓存 MISS 时,查询参数仍可能继续传到源站。

只删除回源参数,则无法保证不同参数变体一定复用同一个缓存对象。

两者组合后才能同时实现:

Plaintext
参数变体共用缓存
+
源站只接收干净 URL

七、EdgeOne 公开列表页分支

公开列表页使用与文章详情页平级的 ELSE IF 分支。

最终使用的正则为:

Plaintext
^(?:/|/page/[1-9][0-9]*/|/category/(?:[^/]+/)+(?:page/[1-9][0-9]*/)?|/(?:tag|series|series-category)/[^/]+/(?:page/[1-9][0-9]*/)?|/[0-9]{4}(?:/[0-9]{2}){0,2}/(?:page/[1-9][0-9]*/)?)$

这条正则覆盖:

  • 首页和首页分页
  • 单级或多级分类及其分页
  • 标签及其分页
  • 系列及其分页
  • 系列分类及其分页
  • 年、月、日归档及其分页

同时不会匹配文章详情页:

Plaintext
/2026/07/30/21863/

列表页分支还设置了以下条件:

Plaintext
查询参数 s:不存在
查询参数 preview:不存在
查询参数 preview_id:不存在
查询参数 preview_nonce:不存在

另外保留了一条特殊端点排除条件:

Plaintext
/(?:feed(?:/(?:rss2|rss|atom|rdf))?|embed|trackback)/?$

运算符为“正则不匹配”。

这可以避免多级分类路径中的 feedembedtrackback 被当成普通分类层级。

例如下面这些地址不会进入公开列表页去参分支:

Plaintext
/category/program-development/feed/
/category/program-development/embed/
/category/program-development/trackback/

列表页分支同样执行:

  • 自定义 Cache Key → 查询字符串 → 全部忽略
  • 回源请求参数设置 → 查询字符串 → 全部忽略
图 2:EdgeOne 公开列表页分支,包含列表页正则、搜索与预览参数保护,以及 Feed、Embed、Trackback 排除条件。
图 2:EdgeOne 公开列表页分支,包含列表页正则、搜索与预览参数保护,以及 Feed、Embed、Trackback 排除条件。

保存发布后,整条规则由文章详情页分支和公开列表页分支组成。

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

八、EdgeOne 测试结果

发布规则后,我对 14 个中文站列表页面分别发起两次请求:

  1. 第一次请求干净 URL;
  2. 第二次请求相同 URL,但附加唯一测试参数。

例如:

Plaintext
https://www.shuijingwanwq.com/page/4/
https://www.shuijingwanwq.com/page/4/?swq_qs_test=随机值

首页和首页分页的结果均表现为:

Plaintext
干净 URL:MISS
带参数 URL:HIT
正文哈希一致

其中首页第一次冷回源的 TTFB 达到了约 14.21 秒,/page/4/ 达到了约 14.68 秒。

而带参数请求复用缓存后,TTFB 降到了约 1.2 秒。

这说明同一个列表页面一旦建立缓存,后续即使带有随机查询参数,也不需要重新执行一次接近 15 秒的 WordPress 冷回源。

分类页、分类分页、标签页和标签分页也都成功表现为:

Plaintext
MISS → HIT

并且正文一致。

以下页面同样被规则覆盖:

  • series-category
  • 系列首页
  • 系列分页
  • 年度归档
  • 月度归档
  • 日期归档
  • 各类归档分页

月度归档出现两次 MISS

测试中,下面两个页面出现了 MISS → MISS

Plaintext
/2026/07/
/2026/07/page/3/

但源站日志显示,两次回源收到的都是没有查询参数的干净 URL:

Plaintext
GET /2026/07/ HTTP/1.1
GET /2026/07/ HTTP/1.1

GET /2026/07/page/3/ HTTP/1.1
GET /2026/07/page/3/ HTTP/1.1

源站没有收到:

Plaintext
?swq_qs_test=...

两次请求分别来自不同的 EdgeOne IP,因此更可能是被调度到了不同的边缘节点,而不是 Query String 规则失效。

九、EdgeOne 搜索页面保护验证

搜索首页仍然返回:

Plaintext
您正搜索 autopoly - 永夜

搜索分页仍然返回:

Plaintext
您正搜索 autopoly - 第2页 共2页 - 永夜

搜索页面与普通首页、普通分页的正文也不同。

源站日志中,测试参数只出现在两条搜索请求里:

Plaintext
/?s=autopoly&swq_qs_test=...
/page/2/?s=autopoly&swq_qs_test=...

其他 14 组文章或列表页请求均没有将测试参数传到源站。

这证明:

  • 普通列表页会忽略缓存 Key 中的 Query String;
  • 缓存 MISS 时,普通列表页不会把 Query String 传给源站;
  • 搜索请求因为存在 s 参数,被正确排除;
  • 搜索首页和搜索分页没有受到影响。

十、Cloudflare 英文站配置

英文站 en.shuijingwanwq.com 使用 Cloudflare。

这里同样没有新建多条 URL Rewrite Rule,而是扩展原有的文章详情页 Query String 规则。

规则名称修改为:

Plaintext
英文文章与公开列表页 Query String 归一化

最终表达式如下:

Plaintext
(
  http.host eq "en.shuijingwanwq.com"
  and http.request.uri.query ne ""
  and (
    (
      starts_with(http.request.uri.path, "/20")
      and substring(http.request.uri.path, 5, 6) eq "/"
      and substring(http.request.uri.path, 8, 9) eq "/"
      and substring(http.request.uri.path, 11, 12) eq "/"
      and ends_with(http.request.uri.path, "/")
      and substring(http.request.uri.path, 12, -1) ne ""
      and not (substring(http.request.uri.path, 12, -1) contains "/")
    )
    or
    (
      not any(http.request.uri.args.names[*] == "s")
      and not any(http.request.uri.args.names[*] == "preview")
      and not any(http.request.uri.args.names[*] == "preview_id")
      and not any(http.request.uri.args.names[*] == "preview_nonce")
      and (
        http.request.uri.path eq "/"
        or (
          starts_with(http.request.uri.path, "/page/")
          and ends_with(http.request.uri.path, "/")
          and substring(http.request.uri.path, 6, -1) ne ""
          and not (substring(http.request.uri.path, 6, -1) contains "/")
        )
        or (
          (
            starts_with(http.request.uri.path, "/category/")
            or starts_with(http.request.uri.path, "/tag/")
            or starts_with(http.request.uri.path, "/series/")
            or starts_with(http.request.uri.path, "/series-category/")
          )
          and ends_with(http.request.uri.path, "/")
          and not (
            ends_with(http.request.uri.path, "/feed/")
            or ends_with(http.request.uri.path, "/feed/rss2/")
            or ends_with(http.request.uri.path, "/feed/rss/")
            or ends_with(http.request.uri.path, "/feed/atom/")
            or ends_with(http.request.uri.path, "/feed/rdf/")
            or ends_with(http.request.uri.path, "/embed/")
            or ends_with(http.request.uri.path, "/trackback/")
          )
        )
        or (
          starts_with(http.request.uri.path, "/20")
          and substring(http.request.uri.path, 5, 6) eq "/"
          and (
            len(http.request.uri.path) eq 6
            or (
              substring(http.request.uri.path, 5, 11) eq "/page/"
              and ends_with(http.request.uri.path, "/")
              and substring(http.request.uri.path, 11, -1) ne ""
              and not (substring(http.request.uri.path, 11, -1) contains "/")
            )
            or (
              substring(http.request.uri.path, 8, 9) eq "/"
              and (
                len(http.request.uri.path) eq 9
                or (
                  substring(http.request.uri.path, 8, 14) eq "/page/"
                  and ends_with(http.request.uri.path, "/")
                  and substring(http.request.uri.path, 14, -1) ne ""
                  and not (substring(http.request.uri.path, 14, -1) contains "/")
                )
                or (
                  substring(http.request.uri.path, 11, 12) eq "/"
                  and (
                    len(http.request.uri.path) eq 12
                    or (
                      substring(http.request.uri.path, 11, 17) eq "/page/"
                      and ends_with(http.request.uri.path, "/")
                      and substring(http.request.uri.path, 17, -1) ne ""
                      and not (substring(http.request.uri.path, 17, -1) contains "/")
                    )
                  )
                )
              )
            )
          )
        )
      )
    )
  )
)

这段表达式覆盖:

  • 文章详情页
  • 首页和首页分页
  • 分类页及其分页
  • 标签页及其分页
  • 系列页及其分页
  • 系列分类及其分页
  • 年、月、日归档及其分页

其中下面这样的未来分页地址也会匹配:

Plaintext
/series-category/example/page/2/
/2026/07/30/page/2/

Cloudflare 重写动作

动作保持为:

Plaintext
路径:保留

查询:
重写到
Static
值留空

也就是保持原始 URL Path,只把 Query String 重写为空。

规则放置在 URL Rewrite Rules 的第一个位置。

最初我对“第一个”这个放置位置有些疑问,但后续实际测试证明,该顺序没有造成冲突,也没有被后面的规则重新添加查询参数。

图 4:Cloudflare URL Rewrite Rule 已处于活动状态,并放置在当前规则列表的第一个位置。
图 4:Cloudflare URL Rewrite Rule 已处于活动状态,并放置在当前规则列表的第一个位置。

十一、Cloudflare 测试结果

英文站测试覆盖了:

  • 文章详情页
  • 首页
  • 首页分页
  • 分类页
  • 分类分页
  • 标签页
  • 系列分页
  • 年度归档
  • 月度归档
  • 日期归档

首页、首页分页、分类页和标签页均表现为:

Plaintext
HIT → HIT

而且两次请求的 Age 连续增长。

例如:

Plaintext
首页 Age:5319 → 5329
首页分页 Age:38470 → 38474
分类页 Age:38723 → 38728
标签页 Age:38210 → 38214

这说明带随机参数的 URL 没有创建新的独立缓存对象,而是复用了现有缓存。

分类分页出现了更直接的结果:

Plaintext
干净 URL:MISS
带参数 URL:HIT
带参数请求 Age:4

日期归档同样表现为:

Plaintext
MISS → HIT

不同边缘节点导致两次 MISS

文章详情页、系列分页和年度归档曾出现:

Plaintext
MISS → MISS

但两次请求的 CF-Ray 分别落在 LASLAX,说明请求进入了不同的 Cloudflare 边缘节点。

源站日志最终确认,这些页面即使发生两次回源,Cloudflare 传给 Nginx 的仍然都是干净 URL:

Plaintext
/2026/07/13/19426/
/category/blog-operations-en/page/2/
/series/wp-blog-multilingual-guide/page/3/
/2026/
/2026/07/
/2026/07/13/

没有任何普通文章或列表请求携带测试参数。

十二、Cloudflare 搜索页面保护验证

英文搜索首页仍然返回:

Plaintext
You are searching for wordpress - Yongye

搜索分页仍然返回:

Plaintext
You are searching for wordpress - Page 2 of 23 - Yongye

搜索页面与普通首页、普通分页的内容也不同。

整个源站日志中,测试参数只出现在两条英文搜索请求里:

Plaintext
/?s=wordpress&swq_cf_qs_test=...
/page/2/?s=wordpress&swq_cf_qs_test=...

这证明英文站同样实现了:

  • 普通文章和列表页删除 Query String;
  • 搜索请求保留 s 参数;
  • 搜索首页和搜索分页不受影响。

十三、为什么 Cloudflare 测试中的 HTML 哈希有时不同

EdgeOne 中文站测试中,干净 URL 和带参数 URL 的完整正文哈希基本一致。

Cloudflare 英文站则有不少页面出现:

Plaintext
same_body: no

即使两个请求都是同一节点的 HIT,完整 HTML 哈希也可能不同。

这并不能直接说明缓存归一化失败。

WordPress 页面中可能存在每次响应都会变化的字段,也可能存在由边缘节点或其他组件注入的动态内容。因此,完整 HTML 文件的 SHA-256 只能作为辅助参考。

这次判断是否成功,主要依据三项证据:

  1. CF-Cache-Status 是否从 MISS 变为 HIT
  2. 同一节点的 Age 是否连续增长;
  3. Nginx 源站日志是否仍能看到测试 Query String。

最终源站日志证明,普通文章和列表页的查询参数确实已经在回源前删除。

十四、最终效果

完成调整后,中文站和英文站都实现了同一套逻辑。

中文站 EdgeOne:

Plaintext
文章详情页和公开列表页
→ 查询参数不参与 Cache Key
→ 缓存 MISS 时不向源站传递查询参数
→ 搜索参数 s 保留

英文站 Cloudflare:

Plaintext
文章详情页和公开列表页
→ Query String 重写为空
→ 不同参数变体复用规范 URL 缓存
→ 缓存 MISS 时源站只收到干净路径
→ 搜索参数 s 保留

以后再出现下面这些请求:

Plaintext
?amp=1
?nonamp=1
?query-5-page=...
?query-62-page=...
?random=value

只要它们落在文章详情页或受支持的公开列表页范围内,就不会再因为参数不同持续制造独立缓存对象和重复回源。

十五、这次优化的局限

Query String 归一化可以显著降低重复回源次数,但不能解决单次冷回源本身过慢的问题。

这次测试中,中文首页和 /page/4/ 的冷回源 TTFB 仍然接近 15 秒,说明 WordPress 列表页面的动态生成速度依然需要继续观察。

不过,这次调整至少解决了一个非常重要的问题:

同一个耗时页面,不会再因为几十种毫无意义的查询参数,被反复当作几十个不同页面执行。

对于只有 1 核 CPU、pm.max_children = 7 的服务器来说,减少不必要的 PHP 请求,比单纯增加 PHP-FPM 进程数量更加实际。

接下来,我会继续观察以下指标:

  • EdgeOne 524 数量
  • Nginx 499 数量
  • PHP-FPM max_children 告警
  • 首页和列表页冷回源耗时
  • EdgeOne 与 Cloudflare 缓存命中率

再根据后续数据判断,是否需要继续优化 WordPress 列表页查询、W3 Total Cache、Redis 对象缓存或源站页面生成速度。

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

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