HTTP 502 Bad Gateway 是网关层错误,不是源站应用主动返回的状态码。在 CentOS 主机上,当前端 Nginx 或 Apache 将请求转发给 PHP-FPM、Node.js、Tomcat 等后端时,如果连接被拒绝、上游进程崩溃、响应超时或返回了不符合协议的头部,网关就会生成 502。因此,定位问题的第一步不是修改代码,而是确认错误发生在哪一层:是后端服务根本没有监听,还是前端代理配置写错了目标地址,还是安全策略切断了本应正常的连接。下面按常见概率从高到低依次排查。

一、根据错误日志判断是连接失败还是上游超时
排查 502 最有效的信息源是前端代理的错误日志。Nginx 默认把错误写入 /var/log/nginx/error.log,Apache 则写入 /var/log/httpd/error_log。如果日志中出现 connect() failed (111: Connection refused) while connecting to upstream,说明请求到达了 Nginx,但目标地址没有服务监听;如果出现 upstream timed out (110: Connection timed out),说明端口可达但后端没有在限定时间内返回;如果出现 upstream sent invalid header,则是后端返回了非法响应头。日志里的 errno 和描述可以大幅缩小排查范围。
建议先打开两个终端的实时日志输出,再复现一次 502。使用 tail -f 查看最近日志,观察是否每次请求都稳定报同样的错误。如果错误随请求变化,可能是偶发资源竞争;如果稳定复现,通常就是配置或服务状态问题。对于 PHP-FPM 自身的问题,还需要检查 /var/log/php-fpm/error.log 或通过 journalctl -u php-fpm 查看进程崩溃原因。
有些管理员习惯只查访问日志,这是不够的。访问日志只会记录状态码为 502,不会说明上游为什么失败。把错误日志级别临时调整到 debug 可以看到更详细的连接与超时信息,但生产环境建议排查结束后恢复,避免日志量过大影响磁盘和性能。
sudo tail -n 50 /var/log/nginx/error.log sudo tail -n 50 /var/log/php-fpm/error.log sudo journalctl -u php-fpm -n 100 --no-pager
二、确认后端服务是否存活以及监听地址是否匹配
在 CentOS 中,502 最常见的直接原因是 PHP-FPM 没有运行或没有监听 Nginx 所配置的地址。先执行 systemctl status php-fpm,确认服务处于 active (running) 状态。如果服务停止,立即执行 systemctl start php-fpm 并设置 systemctl enable php-fpm 开机自启。但不要以为启动成功就结束了,还需用 ss -lntp 或 netstat -lntp 查看 9000 端口或 /run/php-fpm/www.sock 是否真实存在。
Nginx 的 fastcgi_pass 必须与 PHP-FPM 的 listen 完全一致。例如 www.conf 中配置 listen = 127.0.0.1:9000,那么 Nginx 的 fastcgi_pass 也必须是 127.0.0.1:9000;如果 PHP-FPM 使用 Unix socket,如 listen = /run/php-fpm/www.sock,Nginx 要写成 fastcgi_pass unix:/run/php-fpm/www.sock。很多人修改了其中一个文件,漏改另一个,结果一直 502。下面两个配置片段需要成对检查。
资源耗尽导致的 502 也不能忽视。PHP-FPM 采用进程池管理,如果 pm.max_children 设置过小,高并发时后续请求会排队等待空闲 worker,超过 fastcgi_read_timeout 后 Nginx 就会返回 502。查看 PHP-FPM 日志如果出现 server reached pm.max_children setting,就需要结合服务器内存调大进程数,同时使用 pm.max_requests 防止子进程内存泄漏。
; /etc/php-fpm.d/www.conf listen = 127.0.0.1:9000 ; 或者使用 Unix socket:listen = /run/php-fpm/www.sock pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 10 pm.max_requests = 500
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
三、检查 SELinux、firewalld 和 Unix socket 权限
CentOS 默认启用 SELinux,这是很多新手遇到 502 后最困惑的地方。服务在运行、端口也在监听、Nginx 配置无误,但就是连不上,往往是因为 SELinux 策略禁止 Nginx 访问网络或 Unix socket。可以先用 getenforce 查看当前模式,如果是 Enforcing,临时执行 setenforce 0 再刷新页面。如果 502 消失,就说明是 SELinux 拦截。永久关闭 SELinux 并不推荐,正确做法是调整布尔值,例如允许 Nginx 连接上游 TCP 端口时执行 setsebool -P httpd_can_network_connect 1,或者为 socket 设置正确的上下文。
防火墙同样可能造成 502,但主要用于跨主机代理场景。如果 Nginx 和 PHP-FPM 都在同一台 CentOS 上使用 127.0.0.1,通常不受 firewalld 影响;但如果 Nginx 位于另一台服务器,需要访问 CentOS 后端的 9000 端口,就必须放行。执行 firewall-cmd --permanent --add-port=9000/tcp 后重载防火墙。排查时可用 telnet 或 nc 测试端口连通性,避免在防火墙层面浪费太多时间。
使用 Unix socket 时,权限问题非常典型。PHP-FPM 默认以 php-fpm 用户运行,socket 文件位于 /run/php-fpm/www.sock,Nginx 以 nginx 用户运行,如果 socket 权限没有允许 nginx 写入,就会出现 502。检查 socket 权限 ls -l /run/php-fpm/www.sock,并在 www.conf 中显式设置 listen.owner = nginx、listen.group = nginx、listen.mode = 0660,然后重启 PHP-FPM 再测试。
# 查看SELinux状态 getenforce # 查看并放行Nginx连接上游网络的布尔值 getsebool -a | grep httpd_can_network_connect sudo setsebool -P httpd_can_network_connect 1 # 检查Unix socket权限 ls -l /run/php-fpm/www.sock
四、优化超时与缓冲参数避免误报 502
有些 502 并不是服务不可用,而是后端响应太慢,被前端代理提前断开。Nginx 的 fastcgi_read_timeout 默认 60 秒,如果某个 PHP 脚本需要执行 90 秒的报表导出或第三方 API 同步,用户就会看到 502。对这类场景,应该按业务实际耗时调整 fastcgi_read_timeout、proxy_read_timeout 等参数,而不是通过不断重启 PHP-FPM 掩盖问题。对于 Apache 的 mod_proxy_fcgi,对应的是 ProxyTimeout 和 Timeout 指令。
缓冲参数同样会影响 502。如果后端返回的响应头过大,或者本地缓冲区设置过小,Nginx 可能丢弃响应并返回 502。常见提示为 upstream sent too big header while reading response header from upstream。此时可以适当调大 fastcgi_buffer_size、fastcgi_buffers、fastcgi_busy_buffers_size 和 fastcgi_temp_file_write_size。下面示例将缓冲区提升到 16k 和 8 块,适用于大多数 PHP 应用。
另一个容易被忽略的点是后端返回了非法 HTTP 头,例如自定义头中包含下划线或换行符。Nginx 默认会拒绝这些响应并返回 502。检查应用代码中 header 函数的使用,确保头名合法,或者在前端配置中忽略无效头。正式环境建议开启 Nginx 的错误日志 debug 级别,结合响应体内容定位是超时还是头部解析失败。
server {
listen 80;
server_name ipipp.com;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_read_timeout 120s;
fastcgi_buffer_size 16k;
fastcgi_buffers 8 16k;
fastcgi_busy_buffers_size 32k;
fastcgi_temp_file_write_size 32k;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
五、形成固定排查顺序并做好监控
把上面的步骤整理成清单可以大幅提高效率。建议按以下顺序执行:先查看前端错误日志确认错误类型;再检查后端服务 systemctl 状态与端口监听;接着对比 Nginx 与 PHP-FPM 的监听地址和协议;然后验证 SELinux 和防火墙是否拦截;最后根据错误类型调整超时和缓冲区。每一步都优先使用命令行验证,而不是凭感觉猜原因。对于偶发 502,可以在脚本中记录后端响应时间和服务状态,帮助判断是资源瓶颈还是网络抖动。
监控方面,至少应该对 PHP-FPM 进程数、端口存活、错误日志中的 502 关键字进行告警。systemd 可以配置 Restart=on-failure 自动拉起异常退出的后端进程,但不要把自动重启当成唯一手段,否则根因会被隐藏。对于 Nginx 反向代理多台上游,可以使用 upstream 健康检查,将故障节点暂时摘除,避免持续返回 502 影响用户体验。
最后,所有对配置文件的修改都应该重启或重载相关服务并验证:Nginx 使用 nginx -t && systemctl reload nginx,PHP-FPM 使用 systemctl restart php-fpm。修改 SELinux 布尔值或防火墙规则后,也要重新测试页面。只有把每次变更后的验证动作固定下来,才能避免因为漏配、拼写错误或服务未重载而再次出现 502。
502 Bad GatewayCentOSNginx PHP-FPM修改时间:2026-09-27 08:46:58