[网安] 三: 4核服务器CPU满载问题:PHP-FPM进程数优化实战
问题复现
大量cpu满载,但是内存ok,磁盘ok。
看监控曲线,都是正常的。就是硬把cpu跑满了。
梳理一下今天的问题解决过程:
- 问题发现:CPU满载,load average超过50
- 排查发现:php-fpm进程数97个,但配置显示max_children=50
- 深入分析:发现有6个PHP版本同时运行,总最大进程数达490个
- 问题根因:4核CPU运行490个进程,上下文切换开销巨大
- 解决方案:降低各版本max_children参数,调整spare_servers参数
- 最终效果:进程数从97降到23,负载从50+降到0.16
- 后续监控:编写Python监控脚本
debug 问题 部分截图(就让你们看看 参考一下。)
上图,是配置文件一大堆 就不截图全部了
成功:
运维脚本:
4核服务器CPU满载问题:PHP-FPM进程数优化实战
目录
问题背景
服务器配置:
- CPU: Intel Xeon E5-2670 v2 @ 2.50GHz × 2(4核心)
- 内存: 6GB
- 系统: CentOS + 宝塔面板
- Web服务: Apache + PHP多版本
- 网站数量: 约70个网站
问题现象
系统状态异常
[root@ebs-159944 ~]# uptime
14:10:32 up 1:02, 2 users, load average: 52.34, 51.89, 50.25
[root@ebs-159944 ~]# top
%Cpu(s): 98.7 us, 1.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
关键指标异常:
- CPU负载:52.34(4核CPU正常负载应小于4)
- CPU使用率:98.7%
- 系统几乎无响应
排查过程
1. 检查进程数量
[root@ebs-159944 ~]# ps aux | grep php-fpm | wc -l
97
2. 查看PHP-FPM配置
[root@ebs-159944 ~]# cat /www/server/php/74/etc/php-fpm.conf
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
疑点发现: 配置显示最大50个进程,但实际运行97个
3. 深入检查PHP版本
[root@ebs-159944 ~]# ls /www/server/php/
56 70 71 72 73 74 82
[root@ebs-159944 ~]# systemctl list-units | grep php-fpm
php-fpm-56.service loaded active running
php-fpm-70.service loaded active running
php-fpm-71.service loaded active running
php-fpm-72.service loaded active running
php-fpm-73.service loaded active running
php-fpm-74.service loaded active running
真相大白: 6个PHP版本同时运行!
4. 统计各版本配置
find /www/server/php -name "php-fpm.conf" -exec grep "pm.max_children" {} \;
配置汇总:
- PHP 5.6: max_children = 80
- PHP 7.0: max_children = 150
- PHP 7.1: max_children = 80
- PHP 7.2: max_children = 50
- PHP 7.3: max_children = 80
- PHP 7.4: max_children = 50
理论最大进程数: 80+150+80+50+80+50 = 490个进程
根因分析
CPU与进程关系
490个进程 vs 4个CPU核心 = 平均每核心122个进程
问题本质
- 进程切换开销巨大:CPU忙于调度进程而非处理请求
- 资源竞争激烈:大量进程争抢少量CPU资源
- 响应时间延长:请求排队等待CPU调度
理论最佳配置
# 经验公式:max_children = CPU核心数 × 2~4
# 4核CPU建议:32-64个总进程
# 6个版本分配:每版本6-12个进程
解决方案
1. 批量优化进程数配置
# 大幅降低各版本最大进程数
sed -i 's/pm.max_children = 150/pm.max_children = 8/' /www/server/php/70/etc/php-fpm.conf
sed -i 's/pm.max_children = 80/pm.max_children = 6/' /www/server/php/71/etc/php-fpm.conf
sed -i 's/pm.max_children = 80/pm.max_children = 6/' /www/server/php/73/etc/php-fpm.conf
sed -i 's/pm.max_children = 80/pm.max_children = 6/' /www/server/php/56/etc/php-fpm.conf
sed -i 's/pm.max_children = 50/pm.max_children = 6/' /www/server/php/72/etc/php-fpm.conf
sed -i 's/pm.max_children = 50/pm.max_children = 8/' /www/server/php/74/etc/php-fpm.conf
2. 调整spare_servers参数
# 修正spare_servers参数(必须小于max_children)
sed -i 's/pm.min_spare_servers = 5/pm.min_spare_servers = 2/' /www/server/php/56/etc/php-fpm.conf
sed -i 's/pm.max_spare_servers = 20/pm.max_spare_servers = 4/' /www/server/php/56/etc/php-fpm.conf
sed -i 's/pm.start_servers = 5/pm.start_servers = 2/' /www/server/php/56/etc/php-fpm.conf
3. 重启所有PHP服务
systemctl restart php-fpm-56 php-fpm-70 php-fpm-71 php-fpm-72 php-fpm-73 php-fpm-74
4. 处理配置错误
常见错误:
ALERT: [pool www] pm.min_spare_servers(5) and pm.max_spare_servers(8) cannot be greater than pm.max_children(6)
解决方法: 确保参数关系正确
pm.min_spare_servers < pm.max_spare_servers < pm.max_children
优化效果
对比数据
指标 | 优化前 | 优化后 | 改善幅度 |
---|---|---|---|
PHP-FPM进程数 | 97个 | 23个 | ↓76% |
CPU负载(1分钟) | 52.34 | 0.16 | ↓99.7% |
理论最大进程数 | 490个 | 40个 | ↓92% |
系统响应 | 几乎无响应 | 正常 | 完全恢复 |
验证命令
[root@ebs-159944 ~]# ps aux | grep php-fpm | wc -l
23
[root@ebs-159944 ~]# uptime
14:30:13 up 1:22, 2 users, load average: 0.16, 6.44, 26.44
监控脚本
为防止问题复发,编写Python监控脚本:
#!/usr/bin/env python3
# 监控脚本:/www/wwwroot/bobomonitor/server_monitor.py
class ServerMonitor:
def __init__(self):
self.load_threshold = 2.0 # CPU负载告警阈值
self.phpfpm_threshold = 60 # PHP-FPM进程数告警阈值
self.memory_threshold = 85 # 内存使用率告警阈值(%)
self.log_file = "/www/wwwroot/bobomonitor/server_monitor.log"
def check_and_alert(self):
load_avg = self.get_load_average()
phpfpm_count = self.get_phpfpm_count()
memory_usage = self.get_memory_usage()
if load_avg > self.load_threshold:
self.send_alert(f"CPU负载过高: {load_avg}")
if phpfmp_count > self.phpfpm_threshold:
self.send_alert(f"PHP-FPM进程过多: {phpfpm_count}")
宝塔计划任务设置
# 任务类型:Shell脚本
# 执行周期:每5分钟
# 脚本内容:
cd /www/wwwroot/bobomonitor && /usr/bin/python3 server_monitor.py
经验总结
1. PHP-FPM参数最佳实践
# 4核CPU服务器建议配置
pm.max_children = CPU核心数 × 2~3
pm.start_servers = max_children / 4
pm.min_spare_servers = start_servers
pm.max_spare_servers = max_children / 2
2. 多版本PHP优化策略
- 版本整合:关闭不使用的PHP版本
- 按需分配:主要版本分配更多进程
- 总量控制:所有版本总进程数不超过CPU核心数×16
3. 监控告警机制
- 实时监控:每5分钟检查关键指标
- 提前预警:设置合理的告警阈值
- 自动化处理:结合脚本实现自动重启等操作
4. 性能优化要点
- 避免过度配置:根据实际访问量调整参数
- 定期检查:监控长期运行状态
- 版本管理:及时清理无用的PHP版本
- 负载均衡:考虑使用CDN分散请求压力
通过这次优化,不仅解决了CPU满载问题,还建立了完整的监控体系,为服务器稳定运行提供了保障。
关键词: PHP-FPM优化、CPU负载过高、进程数控制、服务器性能调优、宝塔面板
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: