---
canonical: https://meta.cyberforums.com/t/woocommerce-cpu/1860
webpage: https://wpcy.com/community/t/1860-woocommerce-cpu
language: zh-Hans
---

# 实战：WooCommerce 生产站 CPU 爆表排查与三层防护收敛

> 文派叶子支持论坛的只读副本，本页不能回复。
> 讨论原文：https://meta.cyberforums.com/t/woocommerce-cpu/1860
> 网页版：https://wpcy.com/community/t/1860-woocommerce-cpu

## 1 · devops

- 发布时间：2026年3月11日 13:26

背景
电商生产站（WooCommerce）两次 CPU 爆表，load 从正常的 ~3% 飙到 77%（第一次）和 68%（第二次），php-fpm 全部 worker 被打满，站点返回 HTTP 000（连接超时）。
根因
大量爬虫发送 GET 请求，URL 携带 add-to-cart=XXXXX&currency=XXX 参数。这类请求会触发 WooCommerce 完整的加购逻辑（DB 查询 + session 写入），远比普通页面浏览重。
关键特征：

请求方法: GET（正常加购应该是用户点击按钮触发 POST）
无 WooCommerce session cookie（说明不是真实用户）
来自大量不同 IP，伪装各种 Chrome UA
密集翻页：/items/page/N?add-to-cart=XXXXX

sar 数据和 access log 交叉验证，499 状态码（客户端超时断开）占比超过 60%，证实 php-fpm 被打满后新请求全部排队超时。
止血过程（三层→收敛为一层）
第一层：mu-plugin（PHP 层，已清理）
最初在 wp-content/mu-plugins/ 部署 PHP 拦截脚本，检查 GET + add-to-cart + 无 session cookie → 返回 403。
问题：mu-plugin 在 WordPress 完整加载后才执行，每个请求仍然消耗 php-fpm worker 2-3 秒。爬虫量大时 worker 照样被占满。
第二层：auto_prepend_file（PHP 引擎层，已清理）
通过 .user.ini 注册 auto_prepend_file，在 WordPress 加载之前就执行拦截逻辑。
优势：毫秒级返回 403，worker 几乎不被占用。

局限：仍然经过 php-fpm，高并发时仍有开销。
第三层：nginx 规则（最终方案，保留）
在 nginx vhost 配置中，用 nginx 变量组合实现条件判断：
# Anti-bot: block GET add-to-cart without WooCommerce session
if ($request_method = GET) {
    set $block_atc "";
}
if ($arg_add-to-cart) {
    set $block_atc "${block_atc}Y";
}
if ($http_cookie !~* "wp_woocommerce_session_") {
    set $block_atc "${block_atc}N";
}
if ($block_atc = "YN") {
    return 403;
}

逻辑：GET 请求 + 有 add-to-cart 参数 + 无 WooCommerce session cookie → nginx 直接返回 403，PHP 完全不参与。

nginx 不支持 if 嵌套，所以用字符串拼接模拟 AND 条件——这是 nginx 的经典技巧。$block_atc 只有在三个条件都满足时才等于 "YN"。

收敛
确认 nginx 层生效后，清理了 mu-plugin 和 auto_prepend_file，只保留 nginx 单点拦截。减少维护负担，避免多层规则相互干扰。
效果

Load：41 → 1.2（5 分钟内恢复）
爬虫请求：nginx 直接 403，零 PHP 消耗
正常用户：有 WooCommerce session cookie，不受影响
正常加购：真实用户浏览器带 session cookie，正常通过

经验总结

WooCommerce GET add-to-cart 是天然攻击面：任何人拼个 URL 就能触发完整加购逻辑，且 WooCommerce 默认不做频率限制
PHP 层拦截治标不治本：即使返回 403，php-fpm worker 仍被占用。高并发场景必须在 nginx/CDN 层拦截
nginx 多条件判断用字符串拼接：set $var "${var}X" + 最终 if ($var = "XY") 是标准做法
auto_prepend_file 是好的中间方案：当没有 nginx 权限时，比 mu-plugin 快几个数量级
最终应该上 CDN 防护（如 Cloudflare）：在边缘节点就挡掉，连 nginx 都不用处理

## 2 · devops

- 发布时间：2026年3月11日 17:10

后续跟进：两个新问题
问题一：Cavalcade 僵死任务导致反复 CPU 爆表
nginx 爬虫规则部署后，CPU 仍然反复飙高。排查发现第二个根因：Cavalcade（WordPress 后台任务调度器）积压了大量僵死任务。
现象：94万条 failed 任务堆积，4个 running 状态的任务从2月26日就开始了，419个 waiting 任务全部过期被不断重新调度，WP Rocket SaaS 任务单个吃 78% CPU。
根因：Cavalcade runner 的 Worker 类完全没有超时机制。PHP CLI 模式 max_execution_time=0，一个任务挂起后 worker 永远不会被回收。
修复：Worker 加 300 秒超时（SIGTERM→SIGKILL），max_workers 4→2，清理94万 failed jobs + 770万 logs，重启3个 systemd service。
问题二：nginx cookie 检测规则误杀正常客户
原规则逻辑：没有 woocommerce_session cookie 的 GET add-to-cart 请求返回 403。问题是 WooCommerce 的 session cookie 在第一次加购之后才设置，新客户第一次点加入购物车就被 403 了。
修复：改用 rate limit。nginx.conf http 块加 map+limit_req_zone，按 add-to-cart 参数选择性限速（rate=6r/m burst=3 nodelay），超限返回 429。正常用户一分钟内不会连续加购4次以上，爬虫批量请求被429且零PHP消耗。
补充经验

Cavalcade 没有 worker 超时，部署必须自己加
Cookie 检测要考虑首次交互时 cookie 还不存在的情况
nginx map+limit_req 是 WooCommerce 最佳按参数限速方案
