Logo
Overview

WordPress 后台 524/卡顿复盘:EdgeOne 缓存误伤 + Docker 出网被拦的排查与修复

2025/12/23
约 8 分钟阅读

这次故障不是 WordPress 本身也不是 PHP-FPM 参数导致的。真正的根因是两段链路问题叠加:

  1. 容器环回(loopback/REST)请求走了不稳定链路:PHP 容器里请求 https://bubaigei.com/wp-json/ 超时,导致后台(尤其编辑器/健康检查)加载卡顿,EdgeOne 会在源站久不响应时返回 524。
  2. Docker 容器出网被 iptables FORWARD 默认策略 DROP 掐死:宿主机 curl 外网正常,但 PHP 容器 curl api.wordpress.org 超时,导致插件/主题目录加载报错。把 FORWARD 相关规则补齐后恢复。

最终修复:

  • 把容器内访问站点域名的解析指向 host-gateway(172.17.0.1),让 WordPress 自请求不绕边缘/公网回环。
  • 修复并持久化 iptables FORWARD 规则,恢复 Docker bridge 网络出网。

背景环境 🧩

  • VPS:2 核 4G,Debian
  • 面板:1Panel
  • 架构:Docker 容器化的 OpenResty + PHP-FPM + MariaDB + Redis
  • 站点:3 个 WordPress(准备上第 4 个)
  • PHP:8.4.x + OPcache(已启用)
  • 缓存:WP Super Cache + Redis Object Cache
  • 国内站点接入:Tencent EdgeOne(非 Cloudflare)

现象与影响 🔥

现象 1:后台“转圈几秒”,严重时 524

  • 前台秒开(静态/页面缓存命中)
  • 后台打开任意页面都要等,偶发直接超时(EdgeOne 524)

现象 2:插件/主题安装页报错

  • “发生了预料之外的错误…”
  • 站点健康提示:无法与 WordPress.org 通信、REST API/环回请求失败(超时)

排查过程(按时间线复盘)🕵️‍♂️

1)先从 EdgeOne 缓存模板入手:发现“模板不等于可用”

EdgeOne 的 WordPress 缓存模板存在两个典型坑:

  • 规则里只提供 URL path = 等于,没有“前缀/包含/正则”时,/wp-admin/ 并不能覆盖 /wp-admin/*.php
  • 兜底写法(例如把“全站”写成 URL path = /.*)如果仍是“等于”,就等于没写。

采取的缓存策略(最终稳定版)

EdgeOne 只缓存静态资源,其他一律不缓存:

  • IF:静态后缀(js/css/jpg/png/webp/svg/woff2…)→ TTL 7 天
  • ELSE:不缓存

这能避免 HTML/登录态/REST 被边缘缓存误伤,也让“问题归因”更干净。

注:这一步解决的是“缓存误伤/不可控缓存”,但不是最终根因


2)关键证据:PHP 容器里访问自己站点 REST(wp-json)超时

在宿主机执行:

Terminal window
docker exec -it PHP8 sh -lc 'curl -I -m 10 https://bubaigei.com/wp-json/ || true'

结果:curl: (28) Connection timed out after 10000 milliseconds

这条证据直接说明:后台慢不是浏览器/边缘的问题,是源站(容器)自己发 HTTP 请求就卡住了

为什么会影响文章编辑页?

  • WordPress 后台(特别是 Gutenberg 编辑器)大量依赖 REST API。
  • REST/环回慢 → 任何后台页面都可能“转几秒”。

3)第一次误导:把域名映射到“公网 IP”在容器里仍超时

尝试在 compose 里加:

extra_hosts:
- "bubaigei.com:139.155.110.8"

现象:容器 getent hosts 已指向公网 IP,但 curl https://bubaigei.com/wp-json/ 仍超时。

原因:容器访问宿主机公网 IP 常会遇到 NAT 回环/发夹(hairpin NAT)问题,宿主机自己能通但容器不一定能回环成功。


4)关键修复:改用 host-gateway(172.17.0.1)

把 compose 改为:

extra_hosts:
- "bubaigei.com:host-gateway"
- "d4.bubaigei.com:host-gateway"

重建后验证:

Terminal window
docker exec -it PHP8 sh -lc 'getent hosts bubaigei.com; curl -I -m 10 https://bubaigei.com/wp-json/ || true'

输出:解析到 172.17.0.1,并且 HTTP/2 200 秒回

这一步基本解决了:

  • WordPress 后台的 REST/环回超时
  • 后台页面普遍“转圈几秒”的核心卡点
  • EdgeOne 524 的主要诱因(源站迟迟不响应)

5)第二个根因:插件/主题目录仍报错 —— 宿主机能上网,容器不能上网

宿主机:

Terminal window
curl -I -m 10 https://api.wordpress.org/plugins/info/1.2/ || true
# 200 OK

容器(PHP8):

Terminal window
docker exec -it PHP8 sh -lc 'curl -sS -m 10 -o /dev/null -w "HTTP=%{http_code}\n" https://api.wordpress.org/plugins/info/1.2/ || echo FAIL'
# 超时 FAIL

结论:不是 WordPress.org 被墙(宿主机能通),而是 Docker bridge 网络出网被拦


6)快速定位:iptables FORWARD 默认 DROP

查看:

Terminal window
iptables -S FORWARD | head -n 20

结果:-P FORWARD DROP

这会导致:宿主机自己出网没问题,但容器转发/NAT 出网挂掉。


最终修复(可复制的操作清单)🧰

A. 让容器内的“站点自请求”走 host-gateway(解决 REST/环回卡顿)

在 PHP8 的 compose 里:

extra_hosts:
- "bubaigei.com:host-gateway"
- "d4.bubaigei.com:host-gateway"

重建:

Terminal window
docker compose up -d --force-recreate

验证:

Terminal window
docker exec -it PHP8 sh -lc 'curl -I -m 10 https://bubaigei.com/wp-json/ || true'

B. 修复 Docker 出网(解决插件/主题目录、更新检查)

1)开启内核转发

Terminal window
sysctl -w net.ipv4.ip_forward=1

2)在 FORWARD 链插入三条放行规则(更稳,比全局 ACCEPT 更克制)

Terminal window
iptables -I FORWARD 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -I FORWARD 2 -i docker0 -o eth0 -j ACCEPT
iptables -I FORWARD 3 -i eth0 -o docker0 -j ACCEPT

如果默认网卡不是 eth0,用 ip route | grep defaultdev 是什么再替换。

3)验证容器出网

Terminal window
docker exec -it PHP8 sh -lc 'curl -I -m 10 https://api.wordpress.org/plugins/info/1.2/ || true'

C. 持久化(否则重启会复发)💾

1)保存 IPv4 规则

Terminal window
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4

2)安装并启用持久化服务

Terminal window
apt-get update
apt-get install -y iptables-persistent
netfilter-persistent save

3)(可选)生成空的 IPv6 规则文件,避免启动报错

Terminal window
ip6tables-save > /etc/iptables/rules.v6
systemctl restart netfilter-persistent

验收标准 ✅

1)容器内 REST 自请求正常

Terminal window
docker exec -it PHP8 sh -lc 'curl -I -m 10 https://bubaigei.com/wp-json/ || true'
# 200

2)容器内能访问 WordPress.org API

Terminal window
docker exec -it PHP8 sh -lc 'curl -I -m 10 https://api.wordpress.org/plugins/info/1.2/ || true'
# 200

3)后台体验恢复

  • 插件 / 主题安装页可正常加载
  • 站点健康不再报 REST/环回/WordPress.org 通信超时
  • EdgeOne 524 显著减少或消失

经验教训(以后少踩坑)🧠

  1. “前台秒开”并不代表源站健康:前台缓存掩盖了后台/REST 的真实延迟。
  2. 先在容器里测:WordPress 的 cURL/HTTP 请求是在 PHP 容器里发的,不要只看宿主机网络。
  3. EdgeOne/边缘 524 是结果,不是原因:它只是告诉你“源站没及时响应”。要去找“源站为何不响应”。
  4. Docker 出网问题第一眼看 FORWARD-P FORWARD DROP 是典型雷点。
  5. 域名映射别直接指公网 IP:容器访问宿主机公网 IP 可能遇到 hairpin NAT;host-gateway 更稳。

附:一份“以后遇到后台慢/524”快速检查表 ✅

  • 容器内 curl -I -m 10 https://站点/wp-json/ 是否超时?
  • 容器内 curl -I -m 10 https://api.wordpress.org/plugins/info/1.2/ 是否超时?
  • iptables -S FORWARD 是否为 DROP
  • 是否已持久化 /etc/iptables/rules.v4 并启用 netfilter-persistent
  • EdgeOne 是否仅缓存静态,避免后台/REST 被缓存?
  • PHP-FPM pm.max_children 是否过低导致后台排队?(2C4G 多站一般 8 起步更舒服)

备注(可选优化方向)🛠️

  • WP-Cron 改系统 cron,减少后台随机卡顿
  • 定期检查 slowlog,定位慢插件/慢查询
  • EdgeOne 单独给后台域名直连源站(admin 子域名不走边缘),体验更稳但配置略多