您的位置 首页 站点问题

2 核 2G 服务器搭建 WordPress 内存过高问题排查记录

最近在整理 WordPress 服务器配置时,发现一个很常见的问题:一台 2 核 2G 的服务器,网站刚搭好没…

最近在整理 WordPress 服务器配置时,发现一个很常见的问题:一台 2 核 2G 的服务器,网站刚搭好没多久,内存占用就已经接近 80%,偶尔打开后台还会出现卡顿。

很多人的第一反应是服务器配置太低,或者直接重启 PHP、MySQL。重启以后内存确实降下来了,但过几个小时又会涨回去。

说白了,重启只是把现场清空,并没有解决问题。

WordPress 内存过高,可能是 PHP-FPM 进程太多,也可能是 MySQL 参数不合理、插件后台任务堆积,甚至只是 Linux 把空闲内存拿去做了缓存。

所以,看到内存占用 80% 先别急着升级服务器。真正要做的,是先判断这部分内存到底被谁用了。

下面把这次完整的排查思路记录下来。

2 核 2G 运行 WordPress 够不够用?

2 核 2G 运行 WordPress 够不够用

先说结论。

如果只是一个普通博客、企业站或者流量不大的内容网站,2 核 2G 运行 WordPress 通常够用。

前提是服务器配置合理,没有安装一堆高消耗插件,也没有大量动态请求。

一台常规的 WordPress 服务器,主要运行以下几个服务:

  • Nginx 或 Apache
  • PHP-FPM
  • MySQL 或 MariaDB
  • WordPress 程序
  • Redis、面板和监控服务
  • Linux 系统自身进程

真正容易占内存的,一般不是 Nginx,而是 PHP-FPM 和 MySQL。

如果使用宝塔、1Panel 等服务器面板,还要算上面板程序、监控程序和计划任务的消耗。2G 内存看起来不少,但每个服务占一点,很快就没有多少剩余空间了。

所以问题不一定是 WordPress 本身太重,而是服务器上的所有服务加在一起超过了承受范围。

Linux 内存占用高不等于内存不足

排查的第一步,不是修改配置,而是执行:

free -h

输出结果一般会包含:

total
used
free
shared
buff/cache
available

很多人只看 used,发现已经用了 1.7G,就觉得服务器要爆了。

其实不能这么判断。

Linux 会主动把暂时不用的内存拿来做文件缓存。这样下次读取文件时速度更快。如果程序需要更多内存,系统可以释放其中一部分缓存。

相比 free,更值得关注的是 available

如果 available 还有几百 MB,而且服务器没有使用大量 Swap,也没有发生 OOM,那么内存占用看起来很高,不一定是故障。

真正需要警惕的是下面几种情况:

  • available 长期低于 100MB
  • Swap 使用量持续增加
  • 网站频繁出现 502 或 504
  • PHP-FPM、MySQL 经常自动重启
  • 系统日志出现 OOM Killer
  • 后台操作时服务器明显卡顿

也就是说,我们要判断的不是“内存用了多少”,而是“内存还够不够程序继续正常运行”。

WordPress 内存过高怎么查是哪个进程导致的?

先执行下面的命令,按照内存占用对进程进行排序:

ps aux --sort=-%mem | head -20

也可以使用:

top

如果服务器安装了 htop,查看起来会更直观:

htop

重点关注以下进程:

php-fpm
mysqld
mariadbd
nginx
redis-server

如果前十名里大部分都是 PHP-FPM,问题很可能出在 PHP 进程池、WordPress 插件或者动态请求上。

如果 MySQL 一个进程占用了五六百 MB,则要继续检查数据库配置。

如果内存主要被系统缓存占用,而 available 仍然充足,就不需要急着清理。

还可以查看 PHP-FPM 进程的内存:

ps -ylC php-fpm --sort:rss

不同系统的进程名称可能不一样,也可以使用:

ps aux | grep php-fpm
ps aux | grep -E "mysql|mariadb"

这一步的目标很简单:先找到主要内存消耗者,再决定修改什么。

不然上来就改 WordPress 配置、装缓存插件,本质上都是碰运气。

检查服务器是否已经触发 OOM

检查服务器是否已经触发

OOM 是 Out Of Memory 的缩写,也就是系统已经没有足够的内存可以分配。

当物理内存和 Swap 都不够时,Linux 可能会强制杀掉某个进程。被杀掉的经常是 PHP-FPM 或 MySQL,因为它们占用的内存比较多。

执行:

dmesg -T | grep -i -E "oom|killed process"

或者:

journalctl -k | grep -i -E "oom|killed process"

如果日志里出现类似信息:

Out of memory
Killed process
php-fpm
mysqld

那就不是普通的“内存占用高”,而是服务器真的发生过内存耗尽。

这时要重点排查三个问题:

  1. PHP-FPM 是否创建了过多进程;
  2. 单个 PHP 请求是否消耗了过多内存;
  3. MySQL 是否占用了过大的常驻内存。

不要只通过增加 Swap 来掩盖问题。Swap 可以兜底,但不能替代正常的内存配置。

PHP-FPM 进程太多是最常见的问题

WordPress 的 PHP 页面需要交给 PHP-FPM 处理。

当访问量增加,或者某个插件不断发起后台请求时,PHP-FPM 会创建更多工作进程。每个进程都要占用内存。

假设单个 PHP-FPM 进程平均占用 60MB,同时运行 15 个进程,就是:

60MB × 15 = 900MB

对于一台只有 2G 内存的服务器来说,这已经非常高了。

PHP-FPM 常见的进程管理模式有三种:

  • static:固定开启指定数量的进程
  • dynamic:根据请求数量动态增减进程
  • ondemand:有请求时才创建进程,空闲后自动结束

对于访问量不大的 2 核 2G WordPress 网站,我更倾向于使用 ondemand,或者配置得比较保守的 dynamic

PHP-FPM 配置文件的位置因系统和 PHP 版本而异,常见路径包括:

/etc/php/8.2/fpm/pool.d/www.conf
/etc/php-fpm.d/www.conf

可以先查找:

find /etc -name "www.conf" 2>/dev/null

重点检查这些参数:

pm = ondemand
pm.max_children = 6
pm.process_idle_timeout = 10s
pm.max_requests = 500

这里的数字不能照抄,需要根据服务器实际情况调整。

pm.max_children 决定最多允许同时运行多少个 PHP 工作进程。设置太大,访问量一上来就可能直接吃光内存;设置太小,则可能导致请求排队。

一个比较实用的计算方法是:

分配给 PHP-FPM 的内存 ÷ 单个 PHP 进程平均内存

例如给 PHP-FPM 预留 500MB,单个进程平均占用 60MB:

500 ÷ 60 ≈ 8

考虑到还要留出安全空间,可以把 pm.max_children 设置为 6 左右,然后根据访问情况继续观察。

修改后要检查配置并重启 PHP-FPM:

php-fpm -t
systemctl restart php8.2-fpm

具体服务名称需要根据当前 PHP 版本修改。

不要把 PHP memory_limit 当成服务器内存

这是很多 WordPress 新手最容易搞混的地方。

WordPress 中常见下面两个配置:

define('WP_MEMORY_LIMIT', '128M');
define('WP_MAX_MEMORY_LIMIT', '256M');

PHP 配置文件里还有:

memory_limit = 256M

这些参数限制的是单次 PHP 请求最多可以使用多少内存,不是整个服务器只使用这么多内存。

如果 memory_limit 设置成 512M,并不代表 PHP 总共只占用 512M。

假设同时有 6 个 PHP 进程,每个进程都接近 300MB,理论上就可能消耗接近 1.8G 内存。

这也是为什么直接把 WordPress 内存限制调到 512M,并不一定能解决问题,反而可能让小服务器更快触发 OOM。

对于普通 WordPress 网站,前台内存限制可以先从 128M 开始。后台编辑器、导入程序或 WooCommerce 确实需要更多内存时,再根据实际错误适当增加。

如果日志中出现:

Allowed memory size exhausted

才说明某个 PHP 请求碰到了单次内存上限。

这时应该先查清楚是哪个插件、页面或任务消耗了大量内存,而不是无上限地往上加。

WordPress 插件导致内存过高怎么排查?

PHP-FPM 参数限制的是结果,插件和主题问题才可能是原因。

WordPress 中比较容易消耗内存的插件类型包括:

  • 页面可视化编辑器
  • 自动备份插件
  • 安全扫描插件
  • 数据统计插件
  • 相关文章插件
  • 图片压缩插件
  • 数据导入和采集插件
  • WooCommerce 及其扩展
  • 站内搜索和索引插件

如果问题是在安装某个插件以后出现的,可以先停用最近安装的插件。

有 WP-CLI 的情况下,可以查看插件状态:

wp plugin list

临时停用全部插件:

wp plugin deactivate --all

然后逐个恢复:

wp plugin activate 插件名称

每恢复一个插件,就观察一次内存和 PHP-FPM 进程。

当然,正式网站不要在访问高峰期直接停用全部插件。更稳妥的方法是先做备份,再在测试环境中排查。

如果停用全部插件后内存明显下降,说明问题大概率就在插件里。

如果插件全部停用后问题依然存在,可以暂时切换到 WordPress 默认主题,继续排除主题中的自定义代码、查询循环和后台任务。

开启 WordPress 调试日志查异常

可以在 wp-config.php 中加入或修改以下配置:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

错误日志通常会写入:

wp-content/debug.log

重点查找:

  • PHP Fatal error
  • Allowed memory size exhausted
  • 数据库查询错误
  • 重复执行的函数
  • 某个插件不断产生警告
  • 请求超时

生产网站排查结束后,建议关闭调试模式,避免日志文件不断增长:

define('WP_DEBUG', false);

还要检查 debug.log 的文件大小。有些网站问题解决了,但日志没有关闭,最后几 GB 的日志又把磁盘写满了。这种坑不算高级,但确实很常见。

MySQL 内存占用过高怎么优化?

MySQL 本身就需要使用一部分内存作为缓存,所以看到 MySQL 占用两三百 MB 不一定异常。

真正要检查的是它有没有超过这台服务器合理的承受范围。

先登录数据库查看主要参数:

SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';

其中,innodb_buffer_pool_size 是比较关键的参数。

它用于缓存 InnoDB 表和索引。设置得大,可以减少磁盘读取;但在 2G 内存服务器上设置得过大,就会挤压 PHP-FPM 和系统的可用空间。

如果数据库和 WordPress 部署在同一台 2G 服务器上,可以先从 256MB 到 384MB 这个范围观察,而不是直接套用大型数据库服务器的配置。

例如:

[mysqld]
innodb_buffer_pool_size = 256M
max_connections = 50

这只是保守参考值,不是所有网站都必须这样设置。

如果网站并发很低,实际只使用几个数据库连接,就没有必要把 max_connections 设置成几百。因为部分 MySQL 内存会随着连接数量增加而增长。

修改数据库配置前一定要备份,并先确认当前配置文件位置。修改后重启服务,再检查错误日志,避免因为参数写错导致 MySQL 无法启动。

WordPress 数据库还要检查 autoload 数据

有些网站 MySQL 内存和 PHP 内存一起升高,原因不是文章太多,而是 wp_options 表中的自动加载数据太大。

WordPress 每次请求都会加载 autoload 数据。如果某个插件向里面写入了大量配置、缓存或者已经失效的数据,那么每次访问页面都要把这部分内容读出来。

可以先查询自动加载数据的大致体积。不同 WordPress 版本的字段结构可能有差异,常见查询方式为:

SELECT SUM(LENGTH(option_value)) AS autoload_size
FROM wp_options
WHERE autoload = 'yes';

再查体积较大的记录:

SELECT option_name, LENGTH(option_value) AS option_size
FROM wp_options
WHERE autoload = 'yes'
ORDER BY option_size DESC
LIMIT 20;

如果表前缀不是 wp_,需要替换成自己网站使用的前缀。

发现大记录以后,不要直接删除。

先判断它属于哪个插件,确认插件是否仍在使用,再做好数据库备份。很多插件卸载以后会留下配置数据,但也有一些记录是网站正常运行所必需的。

数据库优化不是“看到大表就删”,而是先弄清楚数据是谁写入的。

WP-Cron 后台任务可能让 PHP 进程堆积

WordPress 默认使用 WP-Cron 执行计划任务。

它不是真正的系统定时任务,而是在用户访问网站时检查有没有到期任务。如果某个任务执行很慢,下一批请求又继续触发,就可能出现任务重叠。

常见任务包括:

  • 定时发布文章
  • 备份网站
  • 安全扫描
  • 发送邮件
  • 清理缓存
  • WooCommerce 队列任务
  • 插件同步和数据抓取

可以使用 WP-CLI 查看计划任务:

wp cron event list

如果确认要改用 Linux Crontab,可以在 wp-config.php 中禁用页面访问触发:

define('DISABLE_WP_CRON', true);

然后添加系统定时任务,例如每 5 分钟执行一次:

*/5 * * * * cd /网站目录 && wp cron event run --due-now >/dev/null 2>&1

也可以请求 wp-cron.php,但要根据网站环境设置正确路径和执行用户。

需要注意,禁用 WP-Cron 后必须配置替代任务。不然定时文章、邮件和插件任务都可能不再正常运行。

排查恶意请求和异常爬虫

有时候服务器配置没问题,插件也没有明显异常,但 PHP-FPM 进程还是不断增加。

这时要检查访问日志。

Nginx 日志常见位置是:

/var/log/nginx/access.log

先查看近期请求:

tail -n 200 /var/log/nginx/access.log

统计访问次数较多的 IP:

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head

还要重点关注这些地址:

/wp-login.php
/xmlrpc.php
/wp-admin/admin-ajax.php
/wp-json/

admin-ajax.php 并不一定是攻击请求,很多正常插件也依赖它。但如果它每秒被请求多次,就要继续检查是前端插件、后台任务,还是恶意流量导致的。

xmlrpc.php 如果没有使用需求,可以通过 Web 服务器规则或安全插件限制访问。

对于公开网站,可以使用 CDN、防火墙、登录保护和请求限速降低动态请求压力。

缓存只能减少正常访问造成的 PHP 请求,挡不住所有恶意流量。请求已经大量打到 PHP-FPM 后,再好的页面缓存也可能扛不住。

2G 服务器要不要增加 Swap?

我的看法是:要有,但不要依赖。

先检查当前 Swap:

swapon --show
free -h

如果服务器完全没有 Swap,可以创建一个 1G 左右的 Swap 文件作为兜底:

fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

写入 /etc/fstab,让它重启后自动启用:

/swapfile none swap sw 0 0

还可以适当降低系统使用 Swap 的积极程度:

sysctl vm.swappiness=10

需要永久生效,可以写入系统的 sysctl 配置文件。

Swap 的作用是防止内存短时间耗尽时,系统立即杀死 PHP 或 MySQL 进程。

但是 Swap 使用的是磁盘,速度远低于物理内存。如果网站已经长期大量使用 Swap,服务器通常会明显变慢。

所以,Swap 是安全垫,不是额外赠送的内存。

2 核 2G WordPress 可以参考的优化方向

经过前面的排查,一台普通 2 核 2G WordPress 服务器可以优先从下面几个方向调整:

  1. PHP-FPM 使用 ondemand 或保守的 dynamic 模式;
  2. 根据单个 PHP 进程内存限制 pm.max_children
  3. 不盲目把 PHP memory_limit 调到 512M;
  4. 控制 MySQL Buffer Pool 和最大连接数;
  5. 删除不再使用的高消耗插件;
  6. 检查 wp_options 自动加载数据;
  7. 使用系统 Cron 代替访问触发的 WP-Cron;
  8. 配置页面缓存,减少重复执行 PHP;
  9. 限制登录、XML-RPC 和异常爬虫请求;
  10. 保留适量 Swap,防止突发 OOM。

至于 Redis,不是所有 2G 服务器都必须安装。

Redis 对查询较多的网站有帮助,但它自己也要占内存。如果只是一个访问量很低的博客,页面缓存带来的效果可能比对象缓存更直接。

工具不是装得越多越好。对于小服务器来说,每增加一个常驻服务,都要考虑它到底解决了什么问题。

WordPress 内存优化前后怎么对比?

修改配置以后,不要只看当时的内存。

至少观察几个小时,最好覆盖一次正常访问高峰,并记录:

检查项目 优化前 优化后
系统 available 内存 按实际记录 按实际记录
PHP-FPM 进程数量 按实际记录 按实际记录
单个 PHP 进程内存 按实际记录 按实际记录
MySQL 内存占用 按实际记录 按实际记录
Swap 使用量 按实际记录 按实际记录
后台响应时间 按实际记录 按实际记录
502/504 次数 按实际记录 按实际记录

最好每次只修改一类参数。

如果同时改 PHP-FPM、MySQL、缓存和插件,最后内存降下来了,你也不知道到底是哪项调整起了作用。

排查问题最怕的不是不会改配置,而是改得太多,失去了对比依据。

2 核 2G WordPress 内存过高的最终判断

回到最开始的问题:2 核 2G 服务器运行 WordPress,内存占用 80% 是不是太高?

不一定。

如果 available 内存仍然充足,没有频繁使用 Swap,也没有 OOM 和 502 错误,那么这部分内存可能只是正常缓存。

如果可用内存持续下降,PHP-FPM 进程不断增加,Swap 越用越多,那才说明服务器存在真正的内存压力。

整个排查顺序可以概括成:

先看 available
再查进程
接着查 OOM
然后排查 PHP-FPM
再检查插件、MySQL 和 WP-Cron
最后处理异常流量并配置 Swap

不要一看到 WordPress 内存过高就重启服务器,也不要上来就升级配置。

先把资源消耗的来源找出来。

如果只是 PHP-FPM 参数开得太大,或者一个插件不断执行后台任务,升级到 4G 服务器也只是让问题晚一点出现。

服务器优化这件事,本质上不是把内存占用压得越低越好,而是在有限的配置里,让 PHP、MySQL 和系统之间保持一个稳定的平衡。仅此而已。

本文来自网络,不代表乐行库立场,转载请注明出处:https://www.lexingku.com/meichunguoguao/

作者: tyylf360

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注