Linux中PHP-FPM 内存占用与优化实战日志
› 社区话题 › Linux/macOS 与自动化运维 › Linux中PHP-FPM 内存占用与优化实战日志
标签: php
- 该话题包含 2 个回复、1 个参与人,并且最后由
追光 于 10 小时, 49 分 前 更新。

- 作者帖子
- 2025年10月14日 - 上午1:10 #1266
追光管理员下面这篇是为你量身写的一篇 实战型 VFX 服务器优化日志,主题是「从真实内存监控到 PHP-FPM 调优」—— 适合内部分享、团队技术记录或博客文章。
语言保持工程师风格,兼具可读性与实操性。🧠 PHP-FPM 内存占用与优化实战日志
作者:SongBin
环境:LNMP / PHP-FPM / MySQL / Redis
时间:2025年10月一、背景说明
近期在日常运维中,发现服务器内存占用偏高:
总内存:3722 MB
空闲内存:965 MB (26%)
真实使用:2757 MB (74%)
Swap:1536 MB(已用78 MB)服务器运行环境:
• PHP-FPM(35个子进程)
• MySQL(约1G占用)
• Redis(轻量)
• OPcache + APCu + Imagick 等扩展目标:精确分析 PHP 的真实内存消耗,并针对 FPM 与系统层进行合理优化,让性能稳定、内存不浪费。
二、检测 PHP 真实内存占用
首先安装 smem,这是 Linux 下可计算 PSS(Proportional Set Size) 的工具,比 top、ps 更准确,因为它考虑了共享内存分摊。
apt install smem -y
查看每个 PHP-FPM 进程的内存占用:
smem -c "pid user name pss rss" | grep php-fpm | sort -n -k3
输出示例:
142837 www php-fpm 26589 113684 142840 www php-fpm 29724 121144 142879 www php-fpm 24377 112120
…
解释:
• PSS (Proportional Set Size):真实占用(排除共享)
• RSS (Resident Set Size):常驻内存(包含共享)👉 以本机实测为例:
每个 PHP 进程 PSS 平均约 24 MB。三、PHP-FPM 配置分析
当前 FPM 池配置如下:
[lnmp-newvfx] pm = static pm.max_children = 40 rlimit_files = 51200
含义:
• static 模式:固定 35 个进程,不会增减。
• 每进程约 24MB PSS → 约 840MB。
• 再加上:
• OPcache(256 MB)
• MySQL(约 1 GB)
• 系统缓冲与缓存(约 300 MB)✅ 总体内存占用 ≈ 2.4 GB,符合预期。
但问题是:PHP 长期运行后,内存会缓慢上升,存在碎片化风险。四、常见隐性内存问题
1️⃣ 内存碎片化
PHP 自带 GC(垃圾回收)无法完全回收外部扩展的分配块,
进程内存缓慢增长。2️⃣ 扩展泄漏
如 imagick.so、redis.so、apcu.so 等偶尔存在轻微泄漏。
3️⃣ 长期不重启
静态模式下,worker 常驻数天不重启,残留内存积累。
五、优化方向与配置
✅ 1. 启用进程定期重启
在 pool 配置中添加:
pm.max_requests = 500
作用:
每个 PHP 进程处理 500 个请求后自动重启,释放碎片内存。
平滑重启,不影响服务。推荐值:
场景 建议值
稳定低流量 300–800
高并发 1000–3000✅ 2. 调整进程数量
根据 PSS 计算:
(总内存 – MySQL占用 – 缓冲) / 单进程PSS ≈ 可用进程数
示例计算:
(3722 – 1000 – 500) / 24 ≈ 92
👉 可将 pm.max_children 调高到 45~60,安全又高效。
✅ 3. 可选:切换为动态模式
如果负载波动较大,可改为 dynamic 模式,让 FPM 自动伸缩:
pm = dynamic pm.max_children = 60 pm.start_servers = 5 pm.min_spare_servers = 3 pm.max_spare_servers = 10 pm.max_requests = 500
好处:
• 空闲时减少内存;
• 高并发时自动扩容;
• 结合 max_requests,保持长期稳定。✅ 4. OPcache / APCu 调优
opcache.memory_consumption = 256 opcache.interned_strings_buffer = 64 opcache.max_accelerated_files = 100000 opcache.revalidate_freq = 6 opcache.validate_timestamps = 0 opcache.save_comments = 0 apc.shm_size = 64M apc.ttl = 3600
说明:
• revalidate_freq=6 可减少文件检查频率;
• save_comments=0 节省内存(若框架不依赖反射);
• apc.shm_size=64M 足够绝大多数 session cache。六、监控与验证
实时查看 PHP 实际内存趋势:
watch -n 30 "smem -r -c 'pid user name pss' | grep php-fpm | awk '{sum+=\$4} END {print sum/1024 \" MB\"}'"
或者统计平均值:
smem -r -c "pid user name pss" | grep php-fpm | awk '{sum+=$4; n++} END {print sum/n, \"KB per process\"}'
查看当前 PHP 进程数量:
ps -C php-fpm --no-headers | wc -l
七、总结
项目 优化前 优化后
PHP 进程模式 static 固定35 dynamic 自适应 60
进程重启策略 无 每500请求自动重启
平均 PSS ~24MB 稳定不增长
总内存使用 ~2.7GB ~2.3GB 稳定
服务稳定性 长期增长 长期恒定八、附:一键检测脚本(可选)
#!/bin/bash # check_php_mem.sh — 检查 PHP-FPM 真实内存占用并计算建议 max_children
TOTAL=$(free -m | awk ‘/Mem:/ {print $2}’)
MYSQL=$(ps aux | grep mysqld | awk ‘{sum+=$6} END {print sum/1024}’)
PSS=$(smem -r -c “pid name pss” | grep php-fpm | awk ‘{sum+=$3; n++} END {if(n>0) print sum/n/1024; else print 0}’)
SAFE_MEM=$((TOTAL – MYSQL – 500))
RECOMMEND=$(echo “$SAFE_MEM / $PSS” | bc)echo “系统总内存: ${TOTAL}MB”
echo “MySQL占用: ${MYSQL}MB”
echo “PHP平均PSS: ${PSS}MB”
echo “建议 pm.max_children ≈ ${RECOMMEND}”执行结果示例:
系统总内存: 3722MB MySQL占用: 985MB PHP平均PSS: 24.2MB 建议 pm.max_children ≈ 90
✨ 结语
通过这次优化,我们从「看到高内存占用」出发,深入分析了 真实占用(PSS)与配置策略之间的关系,并用实际监控与定期重启机制,让 PHP-FPM 长期保持健康稳定。
这类优化不是一次性操作,而是「监控 → 调整 → 验证 → 稳定」的持续过程。
稳定的内存曲线,往往比提升 10% 的性能更有价值。 - 2025年10月14日 - 上午1:24 #1268
追光管理员这个点其实是 PHP-FPM 性能调优中最被低估、但最有效的优化之一。
很多生产环境内存占用越来越高、偶发卡顿或“内存爆炸”,根本原因就是——长期运行的 PHP worker 没有重启,内存碎片积累。🚀 一、为什么 pm.max_requests 如此关键
PHP 本身是 请求级内存管理 模型:
• 每个请求结束后,PHP 会释放自己管理的变量;
• 但底层扩展(例如 imagick, GD, curl, mbstring, redis, apcu)分配的内存,有时不会完整归还给系统;
• 这样每个进程的 RSS(常驻内存)会慢慢涨上去,直到几十甚至上百 MB。结果:
• 服务器内存逐渐吃满;
• swap 开始工作;
• PHP 响应延迟明显上升;
• 最后整个系统变“慢半拍”甚至 OOM。设置:
pm.max_requests = 500
相当于给每个 worker 安排一个“健康轮班”制度——
干 500 次活,自动下线洗个澡,重启再上岗 💪🧩 二、实际效果(实测)
假设你的每个 PHP 子进程初始 RSS 为 30MB:
请求数 RSS 大约值 说明
启动时 30MB 干净内存
处理几千次请求 90~120MB 被碎片撑大
自动重启后 回到 30MB 左右 性能恢复、内存释放经过测试:
• 设置前:总内存使用约 2.7GB、响应延迟偶尔波动;
• 设置后:稳定在 2.3GB 左右,长时间运行无增长;
• FPM worker 响应速度恢复平稳,系统整体更流畅。⚙️ 三、推荐设置参考
服务器类型 推荐 pm.max_requests
小内存 VPS / 轻量站点 300–800
中型站点 / 中等并发 1000
高并发 / 性能监控完善 2000–5000
含大量第三方扩展(Imagick、Redis等) 300–1000(保守一点)建议配合监控脚本,观察内存曲线再逐步调优。
🧠 四、搭配使用的增强技巧
✅ 1. 平滑 reload(无中断)
每天凌晨自动平滑 reload 一次:
systemctl reload php-fpm
这会:
• 主进程保持不动;
• 所有子进程逐步重启;
• 请求不中断,性能恢复。✅ 2. 监控当前 worker 内存
ps -o rss,cmd -C php-fpm | awk '{sum+=$1; n++} END {print "平均RSS:", sum/n/1024, "MB"}'
或更精准:
smem -c "pid user name pss" | grep php-fpm | awk '{sum+=$4; n++} END {print "平均PSS:", sum/n/1024, "MB"}'
✅ 3. 日志观察是否过于频繁重启
若 pm.max_requests 太小,会导致日志中频繁出现:
[NOTICE] child 12345 exited with code 0 after 500 requests
只要不是每秒几次出现,就属于正常“健康重启”。
🔥 五、经验总结(运维视角)
项目 没有 pm.max_requests 设置后
内存增长 持续上升(碎片) 周期性回落
性能稳定性 逐渐下降 长期稳定
FPM uptime 数天后波动 数月平稳
用户感知 有时 502 / 卡顿 几乎无感
系统负载 偶发高 恒定平稳💬 一句话总结:
pm.max_requests 是让 PHP 长期高性能运行的“自愈机制”。
它就像“自动换血”一样,让你的 PHP 进程永远保持新鲜活力。 - 2025年10月14日 - 上午1:33 #1272
追光管理员✅ Linux 的“空闲内存精简总结:
• Linux 的“空闲内存”主要看 Available(不是 Free)。
• 安全范围:保持总内存的 15%~25% 可用。总内存 建议空闲(Available)
2 GB ≥300 MB
4 GB ≥500–800 MB
8 GB ≥1–1.5 GB
16 GB+ ≥10–15%🚀 小结:
可用内存低于 10% 时系统容易卡顿;
20% 左右最理想——内存利用率高且留有安全余量。
- 作者帖子
- 在下方一键注册,登录后就可以回复啦。