首先通过系统工具定位CPU占用过高的根源,避免盲目优化。常用命令:
top/htop:按CPU占用排序,查看是php-fpm进程(代码/配置问题)还是mysqld、nginx等其他进程占用过高;strace -p <PID>:跟踪具体PHP进程的系统调用,查看是否频繁执行磁盘I/O、数据库查询等耗时操作;vmstat 1:监控系统整体CPU、内存、I/O使用情况,判断是否存在资源争抢。代码效率低下是CPU占用的常见原因,重点优化以下方面:
count()函数)、冗余的条件判断;SELECT *语句,添加合适的索引(如EXPLAIN分析慢查询),使用缓存(如Redis)存储频繁访问的查询结果;Xdebug或Blackfire生成代码热点报告,定位耗时最长的函数或方法。PHP脚本每次执行都需要编译为字节码,启用OPcache可将编译后的字节码缓存起来,显著减少CPU开销。
php.ini配置:[opcache]
opcache.enable=1 # 开启OpCache
opcache.enable_cli=1 # CLI模式下也启用
opcache.memory_consumption=256 # 缓存内存大小(根据服务器内存调整,如256M/512M)
opcache.max_accelerated_files=20000 # 缓存文件数量上限
opcache.revalidate_freq=2 # 文件更新检查频率(秒)
opcache.fast_shutdown=1 # 快速释放资源
systemctl restart php-fpm。PHP-FPM的进程池配置不当(如进程数不足)会导致CPU排队等待,需根据服务器资源调整:
/etc/php-fpm.d/www.conf(或php-fpm.conf),调整以下参数:pm = dynamic # 使用动态进程管理模式(推荐)
pm.max_children = 50 # 最大子进程数(根据CPU核心数调整,如2核4G服务器设为50)
pm.start_servers = 10 # 启动时的进程数
pm.min_spare_servers = 5 # 最小空闲进程数(保持随时有进程可用)
pm.max_spare_servers = 20 # 最大空闲进程数(避免过多闲置进程浪费资源)
pm.max_requests = 1000 # 每个进程处理的最大请求数(防止内存泄漏累积)
systemctl restart php-fpm。禁用未使用的PHP模块可减少内存和CPU占用:
php.ini,注释掉不需要的模块(如xdebug仅用于开发环境):;zend_extension=/path/to/xdebug.so # 注释掉xdebug
;extension=memcache.so # 注释掉未使用的memcache
systemctl restart php-fpm。引入内存缓存(如Redis、Memcached)存储频繁访问的数据(如会话、数据库查询结果),降低数据库和文件系统的访问频率:
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$cacheKey = 'user_data_' . $userId;
$data = $redis->get($cacheKey);
if (!$data) {
// 缓存未命中,从数据库获取
$data = $db->query("SELECT * FROM users WHERE id = $userId")->fetch();
$redis->set($cacheKey, $data, 3600); // 缓存1小时
}
echo $data;
yum install redis,启动服务:systemctl start redis。Nginx作为反向代理,其配置会影响PHP-FPM的负载:
worker_processes(如worker_processes 4),并绑定CPU核心(worker_cpu_affinity 0001 0010 0100 1000);gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_comp_level 6;
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
expires 30d;
access_log off;
}
systemctl restart nginx。建立监控机制,及时发现CPU占用异常:
htop、glances查看系统资源使用情况;slowlog),定位耗时请求:; php.ini中开启慢日志
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s # 超过5秒的请求记录到慢日志
Prometheus+Granafa或Zabbix设置CPU占用阈值报警(如超过80%时发送邮件/短信)。若以上优化仍无法满足需求,考虑升级服务器硬件: