
先给结论:WordPress 的 cURL error 28 不是一个独立故障,它只表示“请求在规定时间内没有完成”。修复顺序应该是:先确认超时的是哪个 URL,再从服务器本机测 DNS、TCP、TLS、首字节和总耗时,随后排查 IPv6、出站防火墙、WAF、回环请求、重定向以及插件发出的慢请求。直接把 timeout 从 5 秒改成 60 秒,往往只是把报警器的声音调小。
本文适用于“工具 → 站点健康”出现 REST API、回环请求、计划任务或更新检查超时,也适用于 WooCommerce、支付插件、备份插件报 cURL error 28: Operation timed out 的情况。
cURL error 28 到底是什么意思
curl 官方把错误 28 定义为 CURLE_OPERATION_TIMEDOUT:已达到请求指定的超时时间。这个错误只回答“等太久了”,不会替你判断慢在 DNS、连接、TLS、服务器处理还是下载阶段。
WordPress 的 HTTP API 会通过 wp_remote_get()、wp_remote_post() 等函数访问外部服务,也会访问自己。官方的 Site Health 文档说明,回环请求用于运行计划任务,并被主题和插件编辑器用来检查致命错误;更新检查还需要访问 api.wordpress.org。因此同一条 error 28,影响可能从“健康检查有黄点”一直延伸到订单回调、库存同步和备份失败。
先判断是哪一类超时
| 报错位置 | 优先怀疑 | 业务影响 |
|---|---|---|
| REST API 或回环请求 | WAF 拦截本机、DNS 指回错误 IP、HTTPS 重定向循环、PHP 会话 | 区块编辑器、计划任务、插件自检 |
| WordPress 更新 | 出站 443 被封、DNS、CA 证书、WP_HTTP_BLOCK_EXTERNAL |
核心、主题、插件无法更新 |
| 支付或物流插件 | 第三方接口慢、服务器地区线路差、TLS、IPv6 | 支付确认、运单、库存同步 |
| 备份、图片压缩或安全扫描 | 大文件、远程存储慢、PHP 资源不足 | 任务中断或反复重试 |
记录完整报错,尤其是目标 URL、timeout 数值和触发功能。若日志只有“cURL error 28”没有 URL,临时开启 WordPress 调试日志,在复现后查看 wp-content/debug.log;不要在生产站把错误直接显示给访客。
完整排查步骤
第 1 步:一定要从服务器上测试
你的电脑能打开目标网页,不代表服务器能访问它。SSH 登录网站服务器,先测试报错中的真实 URL:
curl -I -L --max-time 15 https://example.com/wp-json/
-I 只取响应头,-L 跟随重定向,--max-time 15 明确给出 15 秒上限。若这里也超时,问题大概率不在 WordPress 页面代码;若命令秒开而 WordPress 超时,再转向 PHP、插件钩子和回环请求。
第 2 步:把总耗时拆成 DNS、连接、TLS 和首字节
curl -sS -o /dev/null \
-w 'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} start:%{time_starttransfer} total:%{time_total}\n' \
--max-time 20 https://example.com/wp-json/
dns很高:检查解析器、/etc/resolv.conf和域名 DNS。connect很高:检查路由、出站防火墙、安全组和目标端口。tls很高或失败:检查系统时间、CA 证书、SNI 和中间证书链。start很高:连接已建立,慢在 PHP、数据库、插件或目标 API 处理。total比前几项高很多:响应体过大或传输线路慢。
第 3 步:对比 IPv4 和 IPv6
curl -4 -I --max-time 15 https://example.com/wp-json/
curl -6 -I --max-time 15 https://example.com/wp-json/
dig +short A example.com
dig +short AAAA example.com
若 IPv4 正常而 IPv6 超时,常见原因是服务器有 IPv6 地址却没有可用的 IPv6 默认路由,或防火墙未放行。正确做法是修复 IPv6 路由/安全组,或者在确认业务不使用 IPv6 后移除错误的 AAAA 解析与主机配置;不要靠反复重试赌 curl 恰好选中 IPv4。
第 4 步:验证 DNS 是否把网站指回正确服务器
curl -I --max-time 15 \
--resolve example.com:443:203.0.113.10 \
https://example.com/wp-json/
把示例 IP 换成源站 IP。--resolve 会绕过 DNS,但仍保留正确的 Host 和 TLS SNI。若强制源站 IP 后正常,问题在 DNS、CDN 回源或分流规则;若仍慢,继续查源站。
第 5 步:检查 WAF、CDN 和出站访问控制
回环请求会让服务器访问自己的公网域名,然后经过 CDN/WAF 再回源。检查:
- WAF 是否把源站公网 IP 当成机器人或异常爬虫;
- 安全组、iptables/nftables 或主机商出站策略是否允许 TCP 443;
- 站点是否在 HTTP/HTTPS、www/非 www 之间循环跳转;
wp-config.php是否设置了WP_HTTP_BLOCK_EXTERNAL。WordPress 官方提醒,这个常量会阻止外部请求;若确需启用,应通过WP_ACCESSIBLE_HOSTS精确放行,而不是把所有限制删除。
WAF 放行应限定为“源站 IP + 本站 Host + 必要路径”,不建议把整站安全规则关掉。若站点运维链路较复杂,可以先按 SHOPAGG 建站课程与实操资料梳理 DNS、CDN、SSL 与 WordPress 的责任边界,再动规则。
第 6 步:确认是不是插件、主题或 PHP 会话拖慢
如果服务器 curl 很快,但 WordPress 内部超时,可以用 WP-CLI 调用同一套 HTTP API:
wp eval 'var_export(wp_remote_get(home_url("/wp-json/"), ["timeout" => 15]));'
WordPress 开发者文档说明,wp_remote_get() 返回响应或 WP_Error。对比 CLI curl 和这条命令,可以判断问题是否进入了 WordPress/PHP 层。
接着在维护窗口使用 Health Check 的故障排除模式,或在暂存站逐个停用最近新增的支付、缓存、安全、备份和远程字体插件。官方还特别指出,活动中的 PHP session 会干扰回环请求;搜索代码或日志中的 session_start(),确保请求结束前调用 session_write_close()。
第 7 步:复测 REST API、回环请求和计划任务
wp cron event run --due-now
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' \
--max-time 15 https://example.com/wp-json/
然后回到“工具 → 站点健康”重新运行测试,并实际验证受影响的业务:创建一篇草稿、执行一次插件更新、触发测试订单或手动运行备份。只看绿色健康状态不够,业务闭环通过才算修复。
哪些处理方式看似有效,其实埋雷
盲目增加 timeout
如果第三方 API 偶尔需要 8 秒而插件只给 5 秒,适度调整可以缓解;但 DNS、IPv6、重定向循环和防火墙不会因为等得久就变正确。先用时间分段找到瓶颈,再决定是否增加超时。
直接禁用 SSL 验证
把 sslverify 设为 false 可能让测试暂时通过,却会放弃证书校验。应更新系统 CA 包、修复完整证书链与服务器时间。
关闭整个 WAF 或防火墙
短时、受控测试可以帮助定位,但不应成为长期方案。最终规则要精确到来源、Host、端口和路径,并保留日志。
在生产站一次停掉所有插件
这可能让结账、缓存和安全同时失效。优先用暂存站或 Health Check 故障排除模式,只对管理员会话模拟停用。
修复验收清单
- 服务器上的 curl 返回预期 HTTP 状态,DNS、连接、TLS 和首字节耗时均合理;
- IPv4/IPv6 结果与站点实际网络配置一致;
- REST API 与回环请求在 Site Health 中通过;
- WP-Cron 能执行到期事件;
- 更新、支付回调、物流同步或备份等原始故障场景已复测;
- 没有通过关闭 SSL 校验、整站 WAF 或无限增加超时来“消除”报错。
error 28 真正有用的地方,是提醒你某一段链路已经超过业务可接受的等待时间。把耗时拆开测,通常比换插件、重装 WordPress 或继续刷新更快找到答案。
作者:庄朋龙,SHOPAGG 独立站与服务器运维编辑。



