Nginx 502/504 排查:从错误日志到PHP-FPM进程池状态

    发布时间:2026-09-10 05:05 更新时间:2026-09-10 05:05 阅读量:0

    网站突然打不开,浏览器里出现 502 Bad Gateway 或 504 Gateway Timeout,这是跑 Nginx + PHP-FPM 的站长最常见的头疼事。很多人的第一反应是重启 Nginx 或 PHP-FPM,但这样做往往治标不治本,过一会儿问题又冒出来。其实,与其盲目重启,不如按顺序做几步排查:先看错误日志确认错误类型,再看 PHP-FPM 进程池是否饱和或脚本是否卡住,最后对症调整超时或进程参数。下面这套思路适用于大多数 Linux 环境下的 Nginx + PHP-FPM 站点,具体路径和参数请以你的实际环境为准。

    先看错误日志:区分 502 与 504 的差异

    Nginx 的 error.log 是排错的起点。默认路径通常是 /var/log/nginx/error.log,宝塔面板等集成环境可能在 /www/wwwlogs 下。用 tail 命令实时查看,或者 grep 当天日期过滤出错误记录:

    tail -f /var/log/nginx/error.log
    grep "30/Sep/2026" /var/log/nginx/error.log | grep -E "502|504"

    日志里最常见的两类报错对应不同问题。一类是 connect() failed(111: Connection refused)或 connect() failed(110: Connection timed out),说明 Nginx 无法连上 PHP-FPM 监听的 socket 或端口。另一类是 upstream prematurely closed connection 或 recv() failed,通常意味着 PHP-FPM 进程在响应过程中崩溃或主动断开。而 504 错误在日志里往往体现为 upstream timed out,说明 PHP-FPM 处理脚本超时,Nginx 等不下去了。

    看懂报错后,先做个快速检查:确认 PHP-FPM 进程是否存活、监听的地址是否和 Nginx 配置一致。用 ps 和 ss 命令查看:

    ps aux | grep php-fpm
    ss -lnp | grep php-fpm

    如果发现 PHP-FPM 根本没有进程,那就直接启动它,再观察是否还会退出。如果进程正常但 Nginx 仍然连不上,多半是两者通信方式不匹配。比如 Nginx 里写的是 127.0.0.1:9000,而 PHP-FPM 改用了 unix socket,或者 socket 文件权限不对。这时需要检查 nginx 配置中的 fastcgi_pass 和 PHP-FPM 的 listen 指令是否对应。

    查看 PHP-FPM 进程池状态与负载

    排除了通信问题后,如果 502/504 仍然间歇性出现,需要看看 PHP-FPM 的进程池是否已经满载。PHP-FPM 内置了 status 接口,可以显示当前活跃进程数、空闲进程数、累计请求数等关键指标。先在 PHP-FPM 配置中启用它,通常是在 www.conf 中设置:

    pm.status_path = /status

    然后在 Nginx 中添加一个 location 规则,仅允许自己的 IP 或内网访问,避免暴露给公网:

    location ~ ^/status$ {
        allow 127.0.0.1;
        deny all;
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
    }

    配置后重启 PHP-FPM 和 Nginx,用 curl 访问 status 接口(如果 PHP-FPM 监听的是 socket,需要在 fastcgi_pass 中写 socket 路径):

    curl http://127.0.0.1/status?full

    输出会包含 pool、process manager、start time、accepted conn、listen queue、max listen queue、listen queue len、idle processes、active processes、total processes 等字段。重点关注 listen queue 是否经常大于 0,或者 max listen queue 值偏高。如果这两个数字大,说明请求到达时进程池已经排满,新请求只能排队等待,一旦队列溢出就会出现 502。同时观察 active processes 是否长期等于 max_children 的上限,如果是,说明进程池规模不够,或者单个请求执行太久占着进程不放。

    除了 status 接口,也可以用 top 或 mpstat 看系统整体负载,确认是 CPU 满还是内存不足。PHP-FPM 每个进程默认占用一定内存,如果 max_children 设置过大导致内存耗尽,系统会触发 OOM Killer,表现为 PHP-FPM 进程消失、Nginx 报 502。留意 dmesg 或 journalctl 中是否有 oom-killer 的记录。

    调整超时与进程管理参数

    找到原因后,调整参数要结合站点实际。如果确认是脚本执行时间超过 Nginx 等待时间导致 504,可以同时调大 Nginx 的 fastcgi_read_timeout 和 PHP-FPM 的 request_terminate_timeout。Nginx 侧在 server 或 location 中加:

    fastcgi_connect_timeout 60s;
    fastcgi_send_timeout 60s;
    fastcgi_read_timeout 60s;

    PHP-FPM 侧在 www.conf 中设置(注意单位是秒):

    request_terminate_timeout = 60
    request_slowlog_timeout = 10s
    slowlog = /var/log/php-fpm-slow.log

    但要注意,超时设太大并不能解决进程卡死的问题,反而会让更多请求堆积。更好的做法是开启慢日志,找出哪些脚本执行时间过长,然后针对性优化。request_slowlog_timeout 设置为 5 到 10 秒,再查看 slowlog 就能定位到具体的 PHP 文件和函数。

    如果频繁出现进程池满载,就需要调整 pm 相关的参数。以常见的动态管理模式为例:

    pm = dynamic
    pm.start_servers = 5
    pm.min_spare_servers = 5
    pm.max_spare_servers = 20
    pm.max_children = 50

    max_children 并不是越大越好,它取决于服务器内存和每个 PHP-FPM 进程的平均内存。建议先观察一段时间,用 ps 命令查看每个进程的内存占用,再估算一个合理值。公式大致是:max_children = 可用内存 / 单个进程平均内存。具体数值需要根据站点流量和业务特点调整,不要照搬别人的配置。

    实际运维中,502 和 504 往往不是单点原因。一套完整的排查流程应该包括:查看 Nginx 错误日志和 PHP-FPM 慢日志,用 status 接口观察进程池状态,结合系统负载和内存使用判断资源是否充足,最后再决定调超时还是调进程数。每次修改配置后,建议用 php-fpm -t 和 nginx -t 检查语法,再平滑重载,避免因配置错误导致服务中断。

    学会这套方法后,下次再遇到 502/504,你会先想到“为什么”,而不是“重启”。从日志到状态,从状态到配置,每一步都有依据,问题自然能更快定位。如果排查后仍然频繁出现,建议进一步检查数据库连接数、第三方接口调用耗时,或者考虑升级配置、增加缓存层来分担压力。

    继续阅读

    📑 📅
    MySQL慢查询日志开启与参数分析:用mysqldumpslow定位拖慢网站的SQL 2026-09-10
    自建网站状态监控:Uptime Kuma部署与告警配置 2026-09-10
    带宽跑满找元凶:iftop、nethogs与tcpdump排查详解 2026-09-10
    WordPress被挂马后的排查与清理:从文件到数据库的完整路径 2026-09-10
    访问日志不会看?goaccess与awk帮你快速定位异常请求 2026-09-09
    宝塔面板安全加固:面板端口、安全入口、SSL与登录告警设置 2026-09-11
    服务器磁盘被写满的排查流程:df与du定位、日志切割与清理注意事项 2026-09-11
    HTTPS证书有效却提示不安全:混合内容的定位与批量修复 2026-09-12
    phpMyAdmin导入大SQL超时:参数调整与命令行导入 2026-09-12
    大文件上传总失败:php.ini与Nginx三处限制如何协调放行 2026-09-14