Ubuntu 上 PHP-FPM 内存占用高怎么办:从排查到调优的实用方法

沿途有光
沿途有光
发布时间:2026-08-23 | 243人浏览过
原创

前言

PHP-FPM 内存占用过高,最怕的不是机器变慢,而是被 OOM Killer 直接清掉进程,站点瞬间白屏。要把这类问题处理稳妥,关键不是盲目调大配置,而是先确认内存到底被谁占走,再根据单进程体积、进程池模式、OPcache 和系统回收策略逐层收紧,最后通过日志和监控验证效果。

PHP-FPM 内存高并不罕见,尤其是在低配 VPS、共享主机或同时承载数据库服务的机器上,一旦内存被吃满,轻则响应变慢,重则被 OOM Killer 直接回收,网站出现白屏。真正有效的处理方式,不是只改一两个参数,而是先确认到底是不是 PHP-FPM 在占内存,再根据机器规格调整进程模型、缓存和系统参数。

下面按排查、配置、缓存、扩展、系统和监控几个层面展开。看完之后,你可以判断:当前瓶颈到底是 PHP-FPM 进程数过多、单进程内存过大、代码存在慢请求,还是系统本身的回收策略不合适。

先确认是不是 PHP-FPM 在吃内存

动手调优前,先把问题源头找准。高内存占用不一定就是 PHP-FPM,也可能是 MySQL、某个 Python 脚本,或者其他后台服务。

PHP-FPM 内存问题排查路径信息图,展示进程确认、单进程内存测算、慢日志定位和参数判断关系。
PHP-FPM 内存排查路径先确认是不是 PHP-FPM 占用内存,再根据单进程内存和慢日志结果决定后续调参方向。

先看高占用进程排位

可以直接用 top,然后按 M 键,按内存占用排序。如果 php-fpm 长期排在前列,基本就能确认方向。

想看得更聚焦,可以用下面这条命令,单独列出 PHP-FPM 进程并按物理内存排序:

ps -ylC php-fpm --sort:rss

算出单个进程平均吃多少内存

这个数值直接决定后面 pm.max_children 能设多大。可用命令如下:

ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%sn", sum/NR/1024,"M") }'

例如一台 1GB 内存的服务器,平均每个 PHP-FPM 进程占用 60MB,那 pm.max_children 设到 15 以上通常就比较危险,因为系统和数据库也需要内存余量。

慢日志往往比配置更关键

如果某些请求执行时间特别长,进程就会长时间占住内存不释放。这类问题只靠调大或调小进程数很难根治。

优先检查慢日志,例如:

/var/log/php-fpm/www-slow.log

不同 PHP 版本或发行版,路径可能略有变化。这里常能看到慢 SQL、死循环、批量处理脚本等线索。

核心是调好 PHP-FPM 进程池参数

大多数情况下,真正影响内存占用上限的,还是进程池配置。配置文件通常位于:

PHP-FPM 进程池与 OPcache 调优信息图,展示不同内存规格的模式选择、关键参数公式和 OPcache 推荐值。
进程池与 OPcache 调优重点进程池参数决定内存上限,OPcache 则影响脚本编译与 IO 开销,两者一起调才能更稳定。
/etc/php/{version}/fpm/pool.d/www.conf

先选对进程管理模式

pm 参数决定 PHP-FPM 用什么方式管理工作进程,不同内存规格的服务器,选择应当不同。

  • 小内存服务器(≤2GB):优先考虑 ondemand 或 dynamic。
  • 大内存服务器(≥4GB):更适合 static,吞吐会更稳定。

原因很简单:小内存机器如果使用 static,在低流量时也会保留一批空闲进程,白白占内存;而大内存机器用固定进程数,能减少频繁创建和销毁进程带来的开销。

几个关键参数怎么估算

pm.max_children 是最重要的上限值,可以按下面的公式估算:

服务器内存(MB) × 0.7 / 单个进程平均内存(MB)

比如 1GB 服务器、单进程平均 60MB:

1024 × 0.7 / 60 ≈ 12

这时把 pm.max_children 设为 12,通常比盲目拉高更稳妥,因为还要给系统、Nginx、数据库预留空间。

其他几个常用参数可以按经验值起步:

  • pm.start_servers:建议设为 CPU核心数 × 2,例如 4 核设为 8。
  • pm.min_spare_servers 和 pm.max_spare_servers:建议设为 CPU核心数 × 1 到 CPU核心数 × 2,例如 4 核可设 4~8。
  • pm.max_requests:建议从 500~1000 开始。

其中 pm.max_requests 很值得重视。它表示单个进程处理一定数量请求后自动重启,这对缓解内存泄漏尤其有效,属于线上环境里很常见的一道保险。

别忽略 OPcache,这一项通常能立刻见效

如果 OPcache 没开,PHP 每次请求都需要重新编译脚本,既浪费 CPU,也增加内存与 IO 压力。对线上环境来说,这通常是必须启用的能力。

先确认在 php.ini 中已经开启:

/etc/php/{version}/fpm/php.ini
opcache.enable=1

几个常见参数的参考值

  • opcache.memory_consumption:一般可设为 128M,大内存服务器可以提高到 256M。
  • opcache.interned_strings_buffer:可设为 32M。
  • opcache.max_accelerated_files:项目文件较多时可设为 10000 或更高。
  • opcache.validate_timestamps:生产环境建议设为 0。

opcache.validate_timestamps=0 的意义在于,PHP 不再频繁检查文件是否被修改,能明显减少磁盘 IO。不过这也意味着代码更新后需要自行 reload 或重启相关服务,适合部署流程规范的生产环境。

清理没用到的 PHP 扩展

默认安装的 PHP 环境,往往会顺手加载不少扩展。单看每一个占用不大,但累积起来,尤其是在多进程模型下,内存成本并不低。

可以在 php.ini 中把不需要的扩展注释掉。常见例子是开发环境调试用的 xdebug,以及业务根本不涉及图片处理时的 gd:

;zend_extension=xdebug.so
;extension=gd.so

改完后记得重启 PHP-FPM,使配置生效:

sudo systemctl restart php{version}-fpm

系统层面的内存回收参数也能帮忙

当服务器本身内存紧张时,只调 PHP-FPM 还不够,内核的回收策略也会影响机器是否容易卡死、是否能及时腾出缓存空间。

系统层与持续监控信息图,展示 sysctl 调整、扩展清理、PHP 升级和监控工具组合。
系统优化与监控闭环当 PHP-FPM 参数已经收紧后,系统回收策略、扩展精简和版本升级。

先看内存回收阈值

可以先查看内核当前的 zone 水位:

grep -E "low|high" /proc/zoneinfo

记下 low 值后,按原文给出的方式计算:乘以 3,再乘以 4(每页是 4KB),可以估算系统开始主动回收内存的临界值。

两项常见 sysctl 调整

第一项是保留最小空闲内存:

sudo sysctl -w vm.min_free_kbytes=524200

这里示例设为 512MB,作用是让系统在接近内存耗尽时,仍保留一部分应急空间,减少整机卡死的概率。

第二项是提高目录项和 inode 缓存的回收积极性:

sudo sysctl -w vm.vfs_cache_pressure=130

默认值一般是 100。如果调到 130,内核会更积极地回收文件系统相关缓存。通常建议在 100~200 区间内观察,不要拉得过高,否则可能影响文件系统性能。

能升级的话,优先考虑升级到 PHP 8.x

如果当前还停留在较旧版本,升级 PHP 本身就是一项有效优化。新版本在执行效率和内存管理上的改善,往往比零碎调参更直接。

原文给出的判断是:同样的代码,在 PHP 8.3 上运行,可能比 PHP 7.4 节省约 20% 的内存,同时执行速度也更快。

以 PHP 8.3 为例,可使用:

sudo apt update && sudo apt install php8.3-fpm

安装完成后重启服务:

sudo systemctl restart php8.3-fpm

调完不是结束,还要继续监控

PHP-FPM 内存优化很少是一锤子买卖。参数改完之后,最好继续观察一段时间,确认峰值内存、慢请求数量和响应时间是否真的改善。

先用实时工具看趋势

  • htop:可按 M 键按内存排序。
  • glances:安装命令为 sudo apt install glances,启动后按 m 键查看内存。

这类工具适合快速判断调整后是否还存在 PHP-FPM 持续堆高的情况。

日志和长期监控要结合看

除了实时观察,还应定期检查:

  • /var/log/php-fpm/error.log
  • www-slow.log

错误日志里可能出现内存泄漏、进程异常退出等线索,慢日志则更适合定位具体脚本和业务逻辑瓶颈。

如果服务器数量较多,或者需要看长期趋势,可以继续搭建 Prometheus + Grafana,把内存使用、进程数和请求耗时做成图表。这样一旦某天内存占用开始异常爬升,通常能比故障发生更早发现问题。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表