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

WordPress 再次出现 CPU 告警:从 EdgeOne 异常流量到自适应频控与 JavaScript 挑战

图 6:为 www 域名单独启用适中的自适应频控和流量防盗刷,处置方式均采用 JavaScript 挑战

作者:

WordPress 性能优化手记

如 如图1 所示,站点健康直接提示这是一个可能对性能或安全性产生重大影响的问题,需要优先解决。

(1) 从站点健康警告到全绿通关

PHP Fatal error: Uncaught RedisException: OOM command not allowed when used memory > 'maxmemory'. in /data/wwwroot/.../wp-content/plugins/w3-total-cache/Cache_Redis.php:150

(2) 解决 WordPress + Polylang 批量处理标签时遇到的 Redis OOM 错误

采用 ondemand 模式,适合 1 核小内存机器,空闲时释放进程。最终配置如下:如图4

(3) 一次WordPress站点504错误的排查与优化实录

优化前最终基准数据:历史累计504错误129条(6月3日峰值126条,为爬虫批量爬标签导致)。

(4) 从单日126次504超时到彻底稳定:WordPress 1核2G服务器极限优化全记录(附全部实操命令)

WebPageTest 核心指标

(5) WordPress性能基准测试与CDN选型实录:从国内拨测到海外WebPageTest,1核2G服务器如何面向全球

页面底部提示“此响应不是合法的 JSON 响应”。

(6) WordPress 标签保存失败?Nginx 限流规则惹的祸 —— 一次完整的 429 问题排查与解决

表示页面仍然是动态生成,没有缓存命中。

(7) WordPress + Nginx + W3 Total Cache 缓存未生效排查全过程(OneinStack 实战)

图7:带 Query String 后,W3TC 显示 Requested URI contains query

(8) WordPress CPU 再次满载:动态参数如何穿透 CDN 与 W3TC 页面缓存

图1:阿里云 ECS 在 14:33~14:42 期间 CPU 使用率持续接近 100%,而内存使用率整体较为稳定

(9) WordPress 服务器 CPU 再次满载:从 Nginx 499、PHP-FPM、Redis 到 W3TC 冷缓存的完整排查

图4:W3TC 最终使用 300 秒 × 7 页,并切换到中英文联合 Sitemap

(10) 从 CPU 告警到双域名预缓存:W3 Total Cache、EdgeOne 与 Cloudflare 96 小时缓存优化实战

WordPress 所有归档模板中使用 Language Visibility 和 WPCode Shortcode 添加中英文 Adsterra 广告

(11) WordPress 三域名架构再次踩坑:Adsterra 归档广告不生效,最终定位到 W3TC Object Cache

WordPress 多语言多域名缓存排查:修复 Polylang + W3 Total Cache 跨 Host 缓存失效问题

(12) WordPress 多语言多域名缓存排查:修复 Polylang + W3 Total Cache 跨 Host 缓存失效问题

WordPress 多域名环境下中文文章详情页未显示 Polylang 语言切换器

(13) WordPress 多域名下 Polylang 语言切换器延迟:W3TC Redis 跨 Host 缓存排查记录

图8:选择 2 核 4 GiB 后显示的实际补差价、2 Mbps 带宽和重启选项

(14) 从 CPU 再次告警到 ECS 升配:WordPress 服务器从 1 核 2G 升级到 2 核 4G 实录

**Alt:** WordPress 生产环境完成 PHP 8.5.9 升级,终端显示 OPcache、Imagick、Redis、Nginx、WordPress 版本及中英文站和后台域名均正常返回 HTTP 200

(15) OneinStack 生产环境将 PHP 8.1.19 升级到 PHP 8.5.9:Imagick 编译失败与 WordPress 多域名缓存验收

阿里云 OneinStack 服务器升级完成,终端显示 Nginx 1.30.4、OpenSSL 3.5.7、PCRE 8.45 和 PHP 8.5.9,Nginx 配置检查成功

(16) 阿里云 OneinStack 实战:将 Nginx 1.24.0 升级到 1.30.4,并同步升级 OpenSSL 3.5.7

阿里云 OneinStack 服务器 Redis 从 7.0.11 升级到 8.10.0 后的版本与运行状态对比截图

(17) 阿里云 OneinStack 实战:将 Redis 7.0.11 升级到 8.10.0,并完成内核优化与回滚保护

GitHub 上为 PublishPress Series 提交 PHP 8.5 SplObjectStorage 弃用警告 Issue 的页面

(18) WordPress 升级 PHP 8.5 后的插件兼容性排查:该修的修,该停的停,该等上游的等

WordPress Post Views Counter 热门文章排行榜区块及浏览量设置界面,用于排查首页查询性能问题

(19) WordPress 动态首页从 19 秒降到 1 秒以内:Post Views Counter 热门文章查询性能问题排查与 MU Plugin 优化实战

WordPress 撰写设置中已开启可能影响网站性能的 Gutenberg 实时协作功能

(20) WordPress 7.0 + PHP 8.5 服务器配置全面审计:PHP-FPM、OPcache、Redis、RDS 与 WordPress 调优实战

【图 1:8 月 6 日提交的 PublishPress Series PHP 8.5 兼容性 Issue #1163 已由上游关闭】

(21) PublishPress Series 3.1.3 升级实录:PHP 8.5 Issue 已修复,却又遇到 Gutenberg 系列编号回归

图 6:为 www 域名单独启用适中的自适应频控和流量防盗刷,处置方式均采用 JavaScript 挑战

(22) WordPress 再次出现 CPU 告警:从 EdgeOne 异常流量到自适应频控与 JavaScript 挑战

今天上午,WordPress 所在的阿里云 ECS 再次出现了 CPU 异常。

这台服务器只有 2 vCPU,平时 CPU 使用率并不高。但这一次 CPU 很快升到接近 100%,而且不是持续几十秒的短暂尖峰,而是维持了相当长一段时间。系统平均负载也同步快速上升,一度达到 13~16 左右。

因为之前已经遇到过类似的高负载情况,所以这一次我首先想到的还是:

是不是又有异常流量突然打到了网站上?

继续查看 EdgeOne 后,很快就找到了一个非常明显的异常时间段。


一、CPU 接近 100%,系统负载同时飙升

从 ECS 监控可以看到,大约从 09:19 开始,CPU 使用率迅速升到接近 100%,并持续到 09:55 左右。

与此同时,系统平均负载也快速上升。

对于一台只有 2 vCPU 的服务器来说,十几的 Load 已经明显超出了正常范围。

图 1:ECS CPU 使用率接近 100%,系统平均负载同时大幅升高
图 1:ECS CPU 使用率接近 100%,系统平均负载同时大幅升高

内存使用率虽然有所波动,但并没有同步耗尽,因此当时首先需要确认的仍然是:

  • 为什么 PHP / WordPress 突然有这么大的计算压力;
  • 是正常流量增长,还是某种异常访问;
  • EdgeOne 是否已经挡住或者缓存了其中一部分请求。

于是我开始查看 EdgeOne 的指标分析。


二、EdgeOne 在几分钟内出现明显的请求峰值

先把 EdgeOne 的时间范围设置为:

Plaintext
2026-09-01 09:10 ~ 10:00

可以很明显地看到,在 09:16 之前访问量还比较正常,从 09:16 左右开始突然快速上升,在 09:20 左右达到峰值,随后又迅速下降。

整个时间范围内,L7 请求总量达到:

Plaintext
2.62 万次

而且流量曲线与服务器 CPU 开始升高的时间基本对应。

图 2:EdgeOne 显示 09:16 后 L7 请求量突然快速增长
图 2:EdgeOne 显示 09:16 后 L7 请求量突然快速增长

这里已经足以说明:

这一次 CPU 告警和突然出现的大量访问之间,很可能存在明显关联。

不过 09:10~10:00 还是一个比较大的时间窗口,因此我继续把范围缩小到流量最集中的:

Plaintext
09:16 ~ 09:23

三、7 分钟内出现约 2.35 万次请求

将时间缩小以后,可以看到:

Plaintext
09:16 ~ 09:23

短短 7 分钟内,EdgeOne 统计到了大约:

Plaintext
2.35 万次 L7 请求

缓存状态大致为:

Plaintext
miss     1.57 万次
hit      6632 次
other    1229 次
dynamic  3 次
图 3:09:16~09:23 的 2.35 万次请求中,EdgeOne Cache Miss 占比较高
图 3:09:16~09:23 的 2.35 万次请求中,EdgeOne Cache Miss 占比较高

一开始看到大量 miss 时,很容易直接理解成:

有一万多次请求直接进入了 PHP。

但实际上并不能这么简单计算。

我的网站架构大致是:

Plaintext
访客

EdgeOne

Nginx

W3 Total Cache Disk Enhanced

PHP-FPM / WordPress

因此 EdgeOne 中的:

Plaintext
miss

准确来说表示:

EdgeOne 节点没有直接命中 CDN 缓存,需要继续向源站请求。

但请求到达源站以后,还可能命中 W3 Total Cache 的页面缓存,并不代表每一次 EdgeOne miss 最终都执行了完整的 WordPress PHP 请求。

所以这张图能够证明的是:

大量请求需要回源。

但仅凭 EdgeOne 的 miss 数量,还不能直接计算到底有多少请求真正执行了 PHP。

这也是后面继续分析源站的原因之一。


四、异常请求并没有集中在少数几个 IP

如果是传统的单 IP 高频访问,最简单的办法通常是:

Plaintext
某个 IP 每分钟超过 N 次
→ 限速或者封禁

但继续查看 EdgeOne 的客户端 IP 分布后,却发现这一次并不是这种情况。

在 09:16~09:23 的 TOP5 客户端 IP 中,最高的单个 IP 也只有:

Plaintext
24 次

其他几个 TOP IP 分别也只有十几次。

图 4:异常时段客户端 IP 高度分散,单个 TOP IP 请求次数并不高
图 4:异常时段客户端 IP 高度分散,单个 TOP IP 请求次数并不高

这意味着总请求量虽然很大,但访问来源非常分散。

换句话说,如果只设置非常简单的:

Plaintext
单 IP 请求频率限制

效果未必理想。

因为一个 IP 的请求量可能完全没有达到阈值,但成百上千个不同 IP 加起来,仍然足以给源站制造很大的压力。

这也是这次流量比较麻烦的地方。


五、请求 URL 同样非常分散

再查看 URL Path 分布,也可以看到类似的特点。

TOP URL 中既有:

Plaintext
/wp-content/plugins/...

这样的资源路径,也有:

Plaintext
/category/...
/tag/...
/feed

之类的 WordPress 页面。

没有出现某一个 URL 被持续几千、几万次集中请求的情况。

图 5:请求 URL 同样较为分散,没有集中在某一个固定页面
图 5:请求 URL 同样较为分散,没有集中在某一个固定页面

因此这一轮流量呈现出来的特点更接近:

Plaintext
大量不同 IP
+
大量不同 URL
+
短时间集中出现

而不是:

Plaintext
少数 IP
+
少数固定 URL
+
持续高速请求

这意味着单纯根据 IP 或单个 URL 做一个很死的限速规则,很容易出现两种结果:

要么设置得太宽松,挡不住这种分散流量;

要么设置得太严格,又容易误伤正常读者和搜索引擎爬虫。


六、源站日志中还出现了异常搜索请求

后续继续检查源站日志时,还发现了一些比较奇怪的 WordPress 搜索请求,例如:

Plaintext
?s=北化研究院+宋丹
?s='PL-I350-1G4
?s=EFEMERIDES+SEPTIEMBRE+PDF

这些关键词彼此之间没有明显关联,也与我博客的主要技术内容没有多少关系。

单看一条搜索请求当然说明不了什么。

但结合前面的特征:

  • 几分钟内突然产生两万多次请求;
  • 来源 IP 高度分散;
  • 请求 URL 高度分散;
  • 搜索关键词也非常随机;

我更倾向于认为,这里面存在相当一部分自动化访问、爬虫或者搜索垃圾流量。

不过我没有把它简单定义成一次明确的“攻击”。

因为仅凭这些数据,还不足以精确判断所有请求的真实来源和目的。

对我来说更重要的是:

不管这些请求最终应该被归类成爬虫、扫描器还是其他自动化流量,它们已经实际导致了一台 2 vCPU 服务器接近满载,因此需要在 EdgeOne 层增加一些防护。


七、将 www 单独使用域名级防护策略

我的主站现在使用的是:

Plaintext
www.shuijingwanwq.com

这次没有直接把整个 EdgeOne 站点的防护策略一起调高,而是让 www.shuijingwanwq.com 使用独立的域名防护策略。

原因也比较简单。

不同子域的业务性质并不完全一样。

如果因为主站遇到异常流量,就直接把所有域名都套上更严格的策略,可能会对其他业务产生没有必要的影响。

所以这一次调整的重点就是:

Plaintext
www.shuijingwanwq.com

八、自适应频控调整为“适中”

EdgeOne 提供了自适应频控。

与自己固定设置:

Plaintext
每个 IP 每分钟最多 N 次

相比,我更希望先让 EdgeOne 根据近期访问基线判断异常访问速度。

最终选择:

Plaintext
规则等级:自适应 - 适中

处置方式使用:

Plaintext
JavaScript 挑战

而不是直接封禁。

这样做主要还是为了降低误伤。

正常使用现代浏览器访问网站的读者,一般能够正常通过 JavaScript Challenge。

而一些简单的自动化脚本和爬虫,则可能因此增加访问成本或者直接无法继续请求。


九、同时开启流量防盗刷

除了自适应频控以外,我还开启了:

Plaintext
流量防盗刷(仅适用于中国大陆地区)

处置方式同样选择:

Plaintext
JavaScript 挑战

最终 www.shuijingwanwq.com 当前主要启用的两项规则就是:

Plaintext
自适应频控
规则等级:自适应 - 适中
处置方式:JavaScript 挑战

流量防盗刷
适用:中国大陆地区
处置方式:JavaScript 挑战
图 6:为 www 域名单独启用适中的自适应频控和流量防盗刷,处置方式均采用 JavaScript 挑战
图 6:为 www 域名单独启用适中的自适应频控和流量防盗刷,处置方式均采用 JavaScript 挑战

我暂时没有继续把规则调得更加激进。

毕竟这是一个公开博客。

Google、Bing、百度以及其他正常爬虫的访问,本身就是网站需要的。

如果因为一次异常流量就把所有自动访问都当成恶意请求处理,很可能会得不偿失。


十、个人版能力有限,只能在现有权限内尽量优化

这里还有一个现实限制需要说明。

我目前使用的是 EdgeOne 个人版本,因此并不是后台里所有安全防护能力都可以使用。

在这次排查过程中,其实有一些更适合针对异常流量做精细控制的配置项,但由于当前版本权限限制,我无法直接配置。

所以这次调整并不是:

已经选择了 EdgeOne 所能提供的最完整防护方案。

而更准确地说是:

在个人版本现有能力和权限范围内,尽量选择最适合当前流量特征、同时又不容易误伤正常访客的组合。

最终能够实际使用并且比较适合当前情况的主要就是:

Plaintext
www 使用独立域名防护策略
+
自适应频控:适中
+
JavaScript Challenge
+
中国大陆地区流量防盗刷

这也是为什么我没有继续围绕固定 IP 阈值设计一大堆复杂规则。

一方面,这次异常流量本身就表现出了明显的分散特征:

Plaintext
IP 分散
+
URL 分散
+
单个 IP 请求量并不高

另一方面,个人版本能够使用的安全能力也存在边界。

因此现阶段更实际的做法,是先充分利用现有版本提供的能力,把明显异常的自动化访问成本提高,同时尽量保证正常读者访问不受影响。

如果以后类似流量持续出现,而且个人版本提供的防护能力已经明显不足,再考虑是否有必要升级版本,或者从其他层面增加更精细的访问控制。


十一、为什么没有直接按 User-Agent 或 IP 封禁?

这次排查以后,我反而更加不倾向于依赖简单的固定规则。

例如按照浏览器 User-Agent:

Plaintext
Chrome
Edge

直接判断是否异常,意义并不大。

自动化程序完全可以伪造正常浏览器 User-Agent。

同样,只依靠 IP 黑名单也很困难。

因为这次 TOP IP 的请求数甚至只有二十多次,而整体请求量却有两万多次。

也就是说:

Plaintext
单个 IP 看起来很正常

并不意味着:

Plaintext
总体流量就是正常的

对这种分布式、低单 IP 频率的自动化访问,自适应判断比单纯写一个固定阈值更适合当前情况。


十二、EdgeOne 的防护只能解决第一层问题

调整 EdgeOne 以后,CPU 最终恢复到了正常范围。

但这次排查没有在这里结束。

因为 EdgeOne 解决的是:

Plaintext
流量入口层

也就是尽量减少不必要的异常请求继续打到源站。

但服务器为什么会在这些请求到来以后这么容易被拖到接近 100% CPU,还需要继续分析:

Plaintext
源站页面缓存是否正常?
PHP-FPM 在执行什么?
WordPress 是否还有其他异常?
W3 Total Cache 的缓存预热是否正常?

继续往服务器里面查以后,我还真的发现了另外一个已经持续了半个月左右的问题:

W3 Total Cache 用于页面缓存预热的联合 Sitemap,竟然从 8 月 14 日以后就一直没有成功更新。

继续追下去又发现:

Plaintext
Yoast post-sitemap.xml

HTTP 500

PHP-FPM memory_limit 256M

Allowed memory size exhausted

这已经不是 EdgeOne 层面的问题了。

所以这一部分我准备单独放到下一篇继续记录。


十三、这次调整后的思路

这次最大的感受是,面对服务器突然满载,不能只看到一个现象就马上归因。

最开始看到:

Plaintext
CPU ≈ 100%

很容易直接认为:

服务器性能不够。

看到 EdgeOne:

Plaintext
miss 1.57 万

又容易直接认为:

一万多次请求全部执行了 PHP。

看到大量随机请求,又容易直接认为:

一定是某个 IP 在攻击。

但继续拆开以后,可以发现事情其实分成了几个不同的层次:

Plaintext
异常自动化流量

EdgeOne 大量回源

源站页面缓存

PHP-FPM

WordPress

每一层都需要单独验证。

因此我现在采取的策略,并不是简单地把 EdgeOne 防护“拉到最高”。

一方面需要控制误伤,另一方面个人版本本身也存在功能和权限限制。

现阶段只能在已有能力范围内,尽量做出更适合当前流量特征的组合:

Plaintext
www 使用独立防护策略
+
自适应频控:适中
+
JavaScript Challenge
+
中国大陆流量防盗刷

先降低明显异常流量对服务器的冲击,再继续处理源站本身的问题。

至于服务器内部到底又发现了什么,就留到下一篇继续整理。

PublishPress Series 3.1.3 升级实录:PHP 8.5 Issue 已修复,却又遇到 Gutenberg 系列编号回归

WordPress 网站维护、性能优化与博客运营咨询

本站已持续运营超过 10 年,累计发布 1000+ 篇原创技术文章,长期实践 WordPress 网站建设、CDN / Cloudflare 配置、缓存优化、Google SEO、广告变现和多语言网站运营。

如果你的 WordPress 网站遇到访问慢、缓存异常、插件冲突、广告不显示、SEO 基础结构混乱、CDN 配置不确定等问题,可以联系我做一次远程技术排查。

适合以下用户:
✅ 个人博客站长
✅ WordPress 网站运营者
✅ 独立开发者与内容创作者
✅ SaaS 产品官网运营团队
✅ 希望优化网站速度与稳定性的站点

服务内容:
✅ WordPress 速度优化
✅ Cloudflare / CDN / 缓存配置排查
✅ 插件冲突与页面异常排查
✅ AdSense 广告显示问题排查
✅ SEO 基础结构检查
✅ 博客运营与商业化咨询

如需了解方案或交流相关问题,请直接联系我,并注明:WordPress 维护咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com