应直连 php-fpm 单 worker 进程用 valgrind 检测内存泄漏,禁用 master 模式并启用调试编译;辅以 php 内置 debug 输出、memory_get_usage 打点及 gc_collect_cycles 验证;通过 pm.max_requests 观察 res 是否递增识别泄漏,排除 opcache、xdebug 等干扰。

直接检测 PHP-FPM 进程本身的内存泄漏,不能靠 Nginx 代理层完成——Nginx 只负责转发请求,内存分配和释放完全发生在 PHP-FPM 子进程中。要准确定位泄漏点,必须绕过 Nginx,让内存分析工具直连 PHP-FPM worker 进程或其等效运行环境。
用 Valgrind 直接分析 PHP-FPM 单进程
Valgrind 不支持 fork 后多进程自动跟踪,而 PHP-FPM 默认以 master-worker 模式运行,会干扰检测。正确做法是禁用 master,启动一个纯前台、单 worker 的 PHP-FPM 实例:
- 修改 php-fpm.conf:设置 daemon = no、master_process = no、process.max = 1
- 确保 PHP 编译时带调试符号:
./configure --enable-debug --with-debug,且未启用 -O2 优化 - 用 Valgrind 启动:
valgrind --leak-check=full --show-leak-kinds=all --log-file=valgrind-php.log /usr/sbin/php-fpm -F -c /etc/php/8.3/fpm/php.ini -y /etc/php/8.3/fpm/php-fpm.conf - 用 curl 或 ab 工具反复触发目标 PHP 脚本(如
curl http://localhost/test-leak.php),再发送kill -QUIT优雅终止进程,Valgrind 将输出完整泄漏报告
配合 PHP 内置调试机制交叉验证
PHP 自身提供轻量级泄漏探测能力,无需外部工具即可快速初筛:
- 编译启用 --enable-debug 的 PHP 后,运行脚本时若发生未释放内存,会在 stderr 输出类似:
=== Total 2 memory leaks detected === - 在可疑脚本中插入
memory_get_usage()和memory_get_peak_usage()打点,对比多次请求后数值是否持续上升 - 调用
gc_collect_cycles()强制触发垃圾回收,再观察内存是否回落;若不回落,大概率是 C 扩展层或静态变量导致的真泄漏
通过 pm.max_requests 识别泄漏模式
这不是检测手段,而是生产环境最实用的“泄漏指示器”:
- 将 php-fpm pool 配置中的 pm.max_requests 设为极小值(如 5 或 10)
- 观察 RES 内存是否随每个新进程重置回低位;若每次重启后内存基线越来越高,说明泄漏跨进程残留(极罕见),更可能是 OPcache 文件失效、共享内存段未清理或扩展 bug
- 配合
systemctl status php8.3-fpm查看子进程生命周期与内存 RSS 趋势,比单纯看 top 更可靠
避免常见干扰项
很多“疑似泄漏”其实是配置或使用误判:
- memory_limit 是 per-request 限制,不是 per-process:即使设为 128M,PHP-FPM 进程总内存仍可远超该值(如 OPcache + 共享内存 + 静态类缓存)
- OPcache 启用时,
opcache.memory_consumption占用独立共享内存段,不计入单个进程 RSS,但总量受系统 shmmax 限制 - Xdebug 开启时会显著放大内存占用,排查前务必用
php -d zend_extension= -f script.php关闭它再测试 - 不要用
valgrind nginx去测 PHP 行为——Nginx 和 PHP-FPM 是两个完全独立的进程,内存空间不共享
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











