PHP-FPM脚本运行时Nginx其他PHP请求阻塞问题求助
问题描述
在Debian 10系统上运行Nginx与PHP7.3-FPM时,出现以下异常:请求包含sleep(60)的慢PHP脚本后,后续请求网站内其他PHP页面会被阻塞,必须等待慢脚本执行完成才能加载;但静态内容可正常加载,推测问题出在PHP-FPM层面。
已配置的PHP-FPM参数:
pm = dynamic pm.max_children = 20 pm.start_servers = 6 pm.min_spare_servers = 3 pm.max_spare_servers = 8
排查步骤
检查PHP-FPM进程占用情况
执行ps aux | grep php-fpm查看活跃子进程数量,确认是否所有pm.max_children配额都被慢请求占满。如果进程数达到20,新的PHP请求会进入等待队列。同时用top或htop观察进程状态,若大量进程处于S(睡眠)状态,说明慢脚本确实在占用进程资源。验证请求队列与连接配置
- 检查PHP-FPM pool配置中的
listen.backlog参数,默认值可能偏小(如128),当进程全被占用时,超过队列长度的请求会阻塞。可尝试调高至listen.backlog = 2048,重启PHP-FPM后测试。 - 若使用Unix Socket连接,执行
ls -l /run/php/php7.3-fpm.sock确认socket文件权限,确保Nginx运行用户(通常为www-data)拥有读写权限,权限不足会导致请求卡在socket层面。 - 若使用TCP连接,用
netstat -tulpn | grep php-fpm确认127.0.0.1:9000处于监听状态,且无本地防火墙规则拦截请求。
- 检查PHP-FPM pool配置中的
启用慢日志定位深层问题
在PHP-FPM pool配置中添加慢日志配置:slowlog = /var/log/php7.3-fpm/slow.log request_slowlog_timeout = 5s重启PHP-FPM后触发慢请求,查看慢日志确认是否存在
sleep(60)之外的阻塞逻辑,比如数据库查询、外部API调用等未被注意到的慢操作。测试进程池并发能力
使用ab工具模拟并发请求验证进程池上限:ab -n 25 -c 25 http://your-domain.com/your-sleep-script.php同时在另一个终端请求普通PHP页面,若并发数未达20就出现阻塞,需检查是否存在其他限制参数,比如
request_terminate_timeout(进程超时时间)或pm.max_requests(进程处理请求数上限)设置不合理。排查会话锁阻塞
若PHP页面使用session_start(),默认会话文件采用独占锁机制:当一个请求持有会话锁时,同会话的其他请求会被阻塞。检查慢脚本是否未及时释放会话锁,可在脚本中尽早调用session_write_close()释放锁,或改用Redis等非文件型会话存储方式。
内容的提问来源于stack exchange,提问作者jrm

