说明:PHP版本为5.6.40,文中配置路径及文件因实际安装配置方式的不同可能有所差异,仅供参考。
1 问题描述:
1.1 XX项目某系统采用nginx+php作为webserver,在使用过程中经常出现访问后台管理页面响应缓慢,甚至无法打开的现象。
1.2 检查Nginx访问日志,发现502状态码,举例如下:
21.5.116.237 – – [19/Aug/2021:10:01:25 +0800] “POST /adminhd/public/Cdrrecord/index HTTP/1.1” 404 555 14.151 14.151 “http://16.5.32.119/adminqd/Pages/serviceconfig/Recordingservice/Manualrecording.html?T=1629336469931&id=101” “Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36” “-“”502” “127.0.0.1:8900” “16.5.32.119”
上述日志中8900为php-fpm监听端口。
1.3 检查php-fpm日志(/usr/local/php/var/log/php-fpm.log),发现如下告警信息:
[19-Aug-2021 14:29:23]WARNING:[pool www] server reached pm.max_children setting (5),consider raising it
2 处理步骤:
2.1 根据上述问题描述1.3查看服务器php-fpm配置文件,并调整参数值。
打开/usr/local/php/etc/php-fpm.conf配置文件,调整如下参数:
pm = dynamic调整为pm = static
pm.max_children = 5调整为pm.max_children = 30
设置完毕需重启php-fpm,重启php-fpm方式:
方式1:systemctl restart php-fpm
方式2:kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
推荐使用第二种方式,平滑重启,不影响现有业务。
2.2 为进一步排查定位并解决问题,可开启php-fpm的slowlog,开启后执行时间长的php会记录到日志中,日志可提供给开发人员分析。
php-fpm开启slowlog方式:
(1)创建log目录:mkdir -p /usr/local/php/log
(2)打开/usr/local/php/etc/php-fpm.conf配置文件,设置如下参数:
slowlog = log/$pool.log.slow
request_slowlog_timeout =5
经过上述设置,执行时长超过5秒的php会记录到日志中。
设置完毕需重启php-fpm。
php-fpm的slowlog内容示例如下:
- Aug-2021 10:02:04] [pool www] pid 19011
script_filename = /var/www/html/adminhd/public/index.php
[0x00007f0edc1a9eb0] execute() /app/webroot/adminhd/adminhd_20210812_1_1.13.1/thinkphp/library/think/db/Connection.php:381
……
……
2.3 调整上述参数后,再次访问页面及查看日志,观察问题描述中所述现象是否依旧。
2.4若Nginx访问日志中没有502状态码,php-fpm日志中也没有server reached pm.max_children setting告警,但访问页面还是缓慢,此时可将php 的slowlog以及相应时间段的mysql慢查询语句提供给研发分析优化。
同时chrome浏览器访问页面时,按F12,选择“网络”,查看各页面元素加载时长,并反馈研发。
3 配置说明
3.1 php-fpm参数配置要根据机器可用内存及实际用户数等实际情况调整进程数量,不能所有项目都用同样的设置。
以上面2.1参数配置举例:
(1)先查看当前每个php-fpm使用的内存,大致估算平均每个php-fpm进程需要多少MB内存,一般20-40MB。
ps -eo pid,lstart,etime,%cpu,%mem,rsz,vsz,args | grep php-fpm

根据rsz列(单位KB)计算php-fpm进程使用的内存,由上图可知单个php-fpm进程使用的最大内存为40320KB。
(2)再根据机器可用内存,计划分配给php-fpm进程的内存,预留给其他应用的内存去确定可以设置的最大进程数。
实例按每个进程使用50M内存(峰值)计算,计划分配1500M内存给php-fpm,得出php-fpm进程数:1500/50=30。
故pm.max_children = 5调整为pm.max_children = 30
因服务器内存充足,闲置内存较多,将pm = dynamic调整为pm = static,这样可提高程序运行效率及稳定性。
3.2 如服务器内存不充足,闲置内存较少,可以将pm设置成dynamic。
pm = dynamic时,同时设置如下参数:
pm.max_children = //允许创建的最大子进程数
pm.start_servers = //设置启动时创建的子进程数目。
pm.min_spare_servers = //设置空闲服务进程的最低数目。
pm.max_spare_servers = //设置空闲服务进程的最大数目。
实际php-fpm进程数根据上述设置会动态调整。
3.3 项目参考配置
小内存服务器设置为动态;大内存服务器、且要求高效率及稳定性,设置为静态。
(1)动态参考配置
配置1:
pm = dynamic
pm.max_children = 40
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
配置2(默认动态线路):
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
(2)静态参考配置
pm = static
pm.max_children = 30