文章资讯 / 云服务器 / 服务器故障排查:网站504错误的nginx错误日志分析和php-fpm参数调优

服务器故障排查:网站504错误的nginx错误日志分析和php-fpm参数调优

发布时间: 分类:云服务器 作者:188mi 来源:互联网 阅读:96

504 多半不是 nginx 的错,而是 php-fpm 排队超时。按清单查 nginx 错误日志定位是 upstream timed out 还是连接被拒,再调 php-fpm 进程数与超时参数,比反复重启有效。

清单 1:先确认这个 504 是谁返回的

先分清是 nginx 自己吐出来的,还是上游超时后转发过来的。浏览器 F12 看 Network 面板的响应头,curl -I https://example.com/xxx 看状态码和 Server 字段。再回到日志对时间点:如果同一秒有 upstream timed out (110: Connection timed out) while reading response header from upstream,方向是后端 PHP 没在超时窗口内返回;如果只有 connect() failed (111: Connection refused),方向是 php-fpm 没起来、socket 路径写错或权限不对。静态资源也 504,基本与 php-fpm 无关,去查 CDN 回源和机房链路。

清单 2:把 nginx 错误日志读出层次

日志默认在 /var/log/nginx/error.log,面板环境常见于 /www/wwwlogs/。别整篇翻,用命令抽特征:

grep -c "upstream timed out" /var/log/nginx/error.log
grep "upstream timed out" error.log | awk -F: '{print $1":"$2}' | sort | uniq -c | sort -rn | head

第二条按小时聚合,能看出峰值落在哪个时段。峰值和业务高峰重合,说明并发能力不足;全天零散出现,多半是个别慢脚本或外部接口卡住。同时留意的关键字还有 worker_connections are not enough(连接数上限)、Too many open files(句柄数)、no live upstreams(后端全被判死)。这几类各有各的处理路径,混在一起调参只会越调越乱。

清单 3:判断 php-fpm 进程池是否被打满

  • 数进程:ps aux | grep php-fpm | grep -v grep | wc -l,和配置里的 pm.max_children 对照,贴顶就是打满了。
  • 开状态页:在池配置里加 pm.status_path = /fpm-status,nginx 加一个只允许内网访问的 location 转发到 fpm socket,然后 curl http://127.0.0.1/fpm-status?full,重点看 max children reached、listen queue、active processes。
  • listen queue 长期大于 0,说明请求在排队;active processes 长期等于 max_children,说明并发容量见底。
  • 算内存:free -m 配合 top -o %MEM,看单个 fpm 进程实际常驻多少。常见量级在三四十兆到七八十兆之间,差异取决于加载的扩展和框架。用可用内存除以单进程占用,再留出两成给系统、数据库和缓存,得到的才是能落地的 max_children。

清单 4:php-fpm 参数调整顺序

  1. 选 pm 模式。流量波动大用 dynamic,稳定高并发用 static,少一层进程调度开销。
  2. 定 pm.max_children。这是核心值,按清单 3 的内存反推结果填,不要照抄网上的固定数字。
  3. 配 pm.start_servers、pm.min_spare_servers、pm.max_spare_servers。dynamic 模式下按 max_children 的四分之一到二分之一取值,避免空闲进程空占内存。
  4. 设 pm.max_requests。给到几百到一千,缓解个别扩展的内存泄漏。
  5. 设 request_terminate_timeout。略大于 nginx 侧的读取超时,避免 nginx 早已返回 504、fpm 还在后台空跑。
  6. 改完必须验证:php-fpm -t 检查语法,再 systemctl reload php-fpm 平滑重载,不要 restart。池配置文件一般在 /etc/php/{版本}/fpm/pool.d/www.conf,面板环境在 /www/server/php/{版本}/etc/php-fpm.d/。动手前先 cp www.conf www.conf.bak。

调大 max_children 不是万能钥匙。进程数上去,内存就被吃掉,MySQL 和 Redis 反而先 OOM,故障形态会从 504 变成 502 或整机失联。

清单 5:慢脚本与超时链条的联动

先开慢日志:request_slowlog_timeout = 5s、slowlog = /var/log/php-fpm/www-slow.log,跑上一两个小时,看慢在哪个文件哪一行。高频原因是循环里查库、同步调用短信或支付接口、没走索引的查询。

超时链条要按从小到大的顺序排:php.ini 的 max_execution_time < request_terminate_timeout < nginx 的 fastcgi_read_timeout 或 proxy_read_timeout。哪一层数值最小,报错就从哪一层冒出来。数据库侧顺带打开慢查询日志,long_query_time 设 1 秒起步,把耗时 SQL 先捞出来。上游若是另一台应用服务器,还要看 proxy_connect_timeout 是否过短,跨机房调用时它经常是隐形瓶颈。

清单 6:改完怎么验证、怎么回滚

  • 压测:用 ab -n 2000 -c 100 https://example.com/ 或 wrk 打一轮,看失败率和 P95 耗时,别只看平均值。
  • 观察:改完 24 小时再统计一次 upstream timed out 条数,和改前对比量级,而不是凭感觉说"好像快了"。
  • 看主机指标:阿里云控制台 → 云监控 → 主机监控,确认 CPU、内存、连接数没有出现新瓶颈;负载高但 CPU 不高,通常是 IO 或数据库在拖。
  • 回滚:保留旧配置副本,cp www.conf.bak www.conf && systemctl reload php-fpm,一分钟内恢复原状。
  • 单机调参顶不住时,方向是加 php-fpm 节点、用 nginx upstream 做负载均衡,或把动态请求与静态资源拆到不同实例。改架构之前,先把日志和状态页的证据留全。

相关工具与阅读