
访问网站时出现“502 Bad Gateway”,通常表示Nginx本身已经接收到请求,但没有从后端服务获得有效响应。
这里的后端服务可能是:
- PHP-FPM;
- Node.js、Java、Python等应用;
- Docker容器中的Web服务;
- 另一台反向代理服务器;
- 负载均衡配置中的上游节点。
因此,遇到502错误时,不应只反复重启Nginx。正确的排查顺序是先确认故障范围,再查看Nginx错误日志,随后检查后端服务、端口或Socket、服务器资源和应用日志。
本文主要适用于Ubuntu、Debian、CentOS、Rocky Linux和AlmaLinux等常见Linux服务器。部分命令需要使用root权限,普通用户可以在命令前添加 sudo。
| 修改生产环境配置前,请备份Nginx及PHP-FPM配置。每次修改后都应先执行配置检查,再平滑重新加载服务。 |
一、什么是502 Bad Gateway
Nginx可以直接处理静态文件,也可以将动态请求转发给其他程序。
例如,WordPress网站通常由Nginx接收HTTP请求,再通过FastCGI将PHP请求交给PHP-FPM:
用户浏览器 → Nginx → PHP-FPM → WordPress和MySQL |
反向代理应用的请求流程可能是:
用户浏览器 → Nginx → Node.js、Java或Python应用 → 数据库及其他服务 |
如果Nginx无法连接后端、连接超时、后端进程异常退出,或者后端返回了无效响应,用户就可能看到502错误。
502表示网关或代理与上游服务之间存在问题,并不一定说明Nginx进程已经停止。
二、先判断故障范围
排查前先确认502出现在哪些请求中。
可以分别测试:
- 所有页面都出现502;
- 只有PHP页面出现502;
- 静态图片和HTML可以访问;
- 只有某个接口出现502;
- 只有访问量高时出现502;
- 只有上传文件或执行耗时任务时出现502;
- 只有某一台上游服务器出现502。
如果静态文件可以访问,而PHP页面全部502,问题通常集中在PHP-FPM、FastCGI配置或Socket权限。
如果只有某个接口或耗时任务出现502,应重点检查后端应用日志、执行时间、内存消耗和Nginx超时配置。
如果所有请求都无法访问,还要检查域名是否连接到了正确的Nginx实例,以及Nginx配置是否加载了正确的站点。
三、检查Nginx是否正常运行
首先查看Nginx状态:
systemctl status nginx --no-pager |
如果Nginx没有运行,可以继续查看最近日志:
journalctl -u nginx -n 100 --no-pager |
检查配置语法:
nginx -t |
正常情况下会看到类似结果:
syntax is ok test is successful |
如果配置检查失败,应根据输出中的文件路径和行号修复问题,不要在配置错误时直接重启Nginx。
确认配置正确后,可以平滑重新加载:
systemctl reload nginx |
重新加载通常不会中断已经建立的正常连接,比直接重启更适合配置变更后的验证。
四、查看Nginx错误日志
Nginx错误日志通常是排查502最有价值的信息。
常见位置包括:
/var/log/nginx/error.log /www/wwwlogs/nginx_error.log /www/wwwlogs/网站域名.error.log |
查看最近100行:
tail -n 100 /var/log/nginx/error.log |
实时观察新错误:
tail -f /var/log/nginx/error.log |
如果不知道实际日志位置,可以查看当前生效配置:
nginx -T 2>/dev/null | grep -n "error_log" |
nginx -T 会输出完整配置。把输出提供给其他人分析前,应先检查其中是否包含域名、内部地址或其他敏感信息。
常见错误日志与原因如下:
| 错误日志关键词 | 常见原因 |
|---|---|
connect() failed (111: Connection refused) | 后端服务未运行或端口错误 |
No such file or directory | PHP-FPM Socket路径不存在或配置不一致 |
Permission denied | Socket或目录权限不正确,也可能受SELinux限制 |
upstream timed out | 后端处理过慢或发生阻塞 |
no live upstreams | 配置的上游节点全部不可用 |
upstream sent too big header | 后端响应头超过当前缓冲区限制 |
recv() failed | 后端进程异常断开连接 |
Connection reset by peer | 后端重启、崩溃或主动关闭连接 |
不要看到502就立即调整超时时间。先根据错误日志确认故障属于连接失败、超时、权限问题还是后端异常。
五、检查PHP-FPM是否运行
WordPress和其他PHP网站出现502时,应优先检查PHP-FPM。
不同系统及PHP版本的服务名称可能不同,例如:
php-fpm php8.1-fpm php8.2-fpm php8.3-fpm php84-php-fpm |
查找PHP-FPM服务:
systemctl list-units --type=service --all | grep -i "php.*fpm" |
假设服务器使用PHP 8.3,可以执行:
systemctl status php8.3-fpm --no-pager |
查看最近日志:
journalctl -u php8.3-fpm -n 100 --no-pager |
如果服务处于停止状态,先检查日志和配置,再尝试启动:
systemctl start php8.3-fpm |
如果PHP-FPM启动后很快再次退出,不要反复重启。常见原因包括:
- PHP-FPM配置语法错误;
- 端口或Socket被占用;
- 扩展加载失败;
- 内存不足导致进程被系统终止;
- 日志或PID目录不存在;
- 配置文件权限异常。
六、检查Nginx与PHP-FPM监听地址是否一致
PHP-FPM可以通过TCP端口或Unix Socket接收FastCGI请求。
TCP端口方式
PHP-FPM可能监听:
listen = 127.0.0.1:9000 |
对应的Nginx配置应类似:
location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass 127.0.0.1:9000; } |
检查端口是否监听:
ss -lntp | grep ":9000" |
如果Nginx连接 127.0.0.1:9000,而PHP-FPM实际监听其他端口,就会出现连接失败。
Unix Socket方式
PHP-FPM可能监听:
listen = /run/php/php8.3-fpm.sock |
对应的Nginx配置应类似:
fastcgi_pass unix:/run/php/php8.3-fpm.sock; |
检查Socket是否存在:
ls -l /run/php/ |
如果PHP升级后Socket文件名发生变化,而Nginx仍然引用旧版本路径,就可能出现:
No such file or directory |
修改时应以PHP-FPM当前生效配置为准,不要通过手动创建空Socket文件解决问题。
七、检查Socket权限
如果Nginx错误日志出现:
connect() to unix:/run/php/php8.3-fpm.sock failed (13: Permission denied) |
说明Nginx进程没有权限访问PHP-FPM Socket。
先查看Nginx运行用户:
grep -n "^user" /etc/nginx/nginx.conf |
再查看Socket权限:
ls -l /run/php/php8.3-fpm.sock |
PHP-FPM池配置中通常包含:
listen.owner = www-data listen.group = www-data listen.mode = 0660 |
实际用户可能是 nginx、www-data 或其他面板创建的用户,应根据服务器环境配置。
不要为了临时解决问题直接设置:
chmod 777 /run/php/php8.3-fpm.sock |
这种做法扩大了访问权限,而且Socket通常会在PHP-FPM重启后重新创建,手动修改可能失效。正确做法是调整PHP-FPM池的 listen.owner、listen.group 和 listen.mode,然后检查配置并重新加载服务。
八、检查后端应用端口
如果Nginx反向代理Node.js、Java、Python或Docker应用,先从服务器本机访问后端。
假设Nginx配置为:
location / { proxy_pass http://127.0.0.1:3000; } |
检查端口:
ss -lntp | grep ":3000" |
直接请求后端:
curl -I --max-time 10 http://127.0.0.1:3000/ |
如果后端只对特定路径响应,也可以测试实际健康检查接口:
curl -i --max-time 10 http://127.0.0.1:3000/health |
可能出现以下结果:
Connection refused:应用未监听该端口;- 请求超时:应用阻塞、地址错误或网络受限;
- 返回500:应用已经接收请求,但内部执行失败;
- 返回200:后端基本可访问,应继续检查Nginx转发配置和请求头;
- 返回404:端口可访问,但测试路径不存在。
注意,应用如果只监听 127.0.0.1,其他服务器不能通过内网IP访问;如果只监听IPv6地址,Nginx连接IPv4地址也可能失败。
九、检查Docker容器
后端运行在Docker中时,先查看容器状态:
docker ps -a |
查看应用日志:
docker logs --tail 100 容器名称 |
检查端口映射:
docker port 容器名称 |
查看容器重启情况:
docker inspect -f '{{.State.Status}} {{.State.Restarting}} {{.RestartCount}}' 容器名称 |
常见问题包括:
- 容器已经退出;
- 应用在容器内启动失败;
- 容器没有发布对应端口;
- Nginx连接了错误的宿主机端口;
- 应用只监听容器内的
127.0.0.1; - 容器因内存不足被终止;
- Docker网络或服务名称配置错误。
不要只执行 docker restart。如果容器不断重启,应根据容器日志修复应用、配置或资源问题。
十、检查服务器CPU、内存和磁盘
服务器资源耗尽会导致PHP-FPM或其他后端进程无法正常响应。
查看负载和内存:
uptime free -h |
查看磁盘容量和inode:
df -h df -i |
查看占用资源较高的进程:
ps aux --sort=-%mem | head ps aux --sort=-%cpu | head |
检查是否发生过OOM:
journalctl -k --since "2 hours ago" | grep -Ei "out of memory|killed process|oom" |
如果日志显示PHP-FPM、MySQL、Java或容器进程被OOM Killer终止,应减少进程并发、优化应用内存,或者在评估后增加服务器内存。
单纯重启服务只能暂时恢复,不能解决持续的内存不足。
十一、PHP-FPM进程达到上限
PHP-FPM的 pm.max_children 决定一个进程池能够同时处理的请求数量上限。
如果PHP-FPM日志出现类似信息:
server reached pm.max_children setting |
说明当前进程数已经达到配置上限,新请求需要等待,严重时可能引发超时或502。
查找配置:
grep -R "^[[:space:]]*pm.max_children" /etc/php/*/fpm/pool.d/ 2>/dev/null |
不同发行版和安装方式的配置路径可能不同,例如:
/etc/php/8.3/fpm/pool.d/www.conf /etc/php-fpm.d/www.conf |
不要盲目把 pm.max_children 调得很大。可以先观察单个PHP-FPM进程的内存:
ps --no-headers -o rss,cmd -C php-fpm | sort -n |
粗略估算时,需要确保:
PHP-FPM可用内存 ÷ 单个PHP进程在业务高峰时的实际内存 ≥ pm.max_children |
同时还要为Nginx、MySQL、系统和其他服务保留内存。
如果请求长期占用PHP进程,应继续检查慢查询、外部接口、插件和应用代码,而不是只增加进程数量。
十二、后端处理超时
Nginx官方文档中,fastcgi_read_timeout 和 proxy_read_timeout 默认值通常为60秒。它们限制的是两次连续读取之间允许等待的时间,而不是整个响应传输的总时间。
PHP-FPM场景可以配置:
location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/run/php/php8.3-fpm.sock; fastcgi_read_timeout 120s; } |
反向代理场景可以配置:
location / { proxy_pass http://127.0.0.1:3000; proxy_connect_timeout 10s; proxy_read_timeout 120s; proxy_send_timeout 120s; } |
修改后检查并重新加载:
nginx -t && systemctl reload nginx |
增加超时时间只适用于业务确实需要较长执行时间的情况,例如数据导入、报表生成或受控的后台任务。
如果普通页面也要等待几十秒,应该优先排查:
- MySQL慢查询;
- 第三方接口超时;
- DNS解析异常;
- PHP插件阻塞;
- 文件锁;
- 应用死循环;
- 磁盘IO过高;
- 后端线程或连接池耗尽。
无限增加超时时间会让请求占用连接和进程更久,可能进一步放大故障。
十三、上游响应头过大
如果错误日志出现:
upstream sent too big header while reading response header from upstream |
常见原因包括:
- Cookie过多或过大;
- 应用返回大量响应头;
- 登录状态或Session数据异常;
- 上游返回多个体积较大的
Set-Cookie; - 应用错误地把大量数据写入响应头。
PHP-FPM场景可能涉及:
fastcgi_buffer_size 32k; fastcgi_buffers 8 16k; |
反向代理场景可能涉及:
proxy_buffer_size 32k; proxy_buffers 8 16k; |
这些数值只是示例,不应直接复制到所有服务器。应先检查浏览器Cookie和后端响应头,优先修复异常数据,再根据实际响应大小调整缓冲区。
十四、检查SELinux
在启用SELinux的CentOS、Rocky Linux或AlmaLinux服务器上,即使文件权限看起来正常,安全策略也可能阻止Nginx访问Socket或连接网络后端。
查看状态:
getenforce |
查看近期拒绝记录:
ausearch -m AVC -ts recent 2>/dev/null | tail -n 50 |
不要把永久关闭SELinux作为默认解决方法。应根据拒绝日志修复文件安全上下文、布尔策略或服务配置。
为了测试而临时改变安全策略前,也应明确影响范围并准备恢复操作。
十五、检查上游服务器配置
使用 upstream 配置多个后端时,示例可能如下:
upstream app_backend { server 10.0.1.10:8080; server 10.0.1.11:8080; } server { location / { proxy_pass http://app_backend; } } |
如果错误日志出现:
no live upstreams |
应分别检查每个节点:
curl -I --max-time 10 http://10.0.1.10:8080/ curl -I --max-time 10 http://10.0.1.11:8080/ |
同时确认:
- 后端服务是否运行;
- 内网路由是否正常;
- 安全组和防火墙是否允许访问;
- 端口是否正确;
- 健康检查是否与应用路径匹配;
- 所有节点是否同时进入不可用状态。
在没有理解请求是否可以安全重试之前,不要随意扩大 proxy_next_upstream 的重试范围,尤其是涉及支付、创建订单和修改数据的POST请求。
十六、面板服务器如何排查
宝塔、1Panel等面板会改变配置目录、日志位置和PHP服务名称,但排查原则不变:
- 查看网站对应的Nginx错误日志;
- 检查PHP或应用进程状态;
- 对比Nginx与后端监听地址;
- 检查服务器资源;
- 修改配置前创建备份;
- 修改后执行Nginx配置检查。
面板中的“重启PHP”和“重启Nginx”可以用于恢复服务,但如果问题重复发生,仍应根据日志查找进程退出、资源不足或配置不一致的根因。
十七、502快速排查流程
可以按照下面的顺序执行。
第一步:检查Nginx
systemctl status nginx --no-pager nginx -t |
第二步:查看错误日志
tail -n 100 /var/log/nginx/error.log |
第三步:检查后端服务
PHP网站:
systemctl list-units --type=service --all | grep -i "php.*fpm" |
反向代理:
ss -lntp curl -I --max-time 10 http://127.0.0.1:后端端口/ |
第四步:检查监听配置
确认以下配置一致:
Nginx fastcgi_pass ↔ PHP-FPM listen |
或者:
Nginx proxy_pass ↔ 应用实际监听地址和端口 |
第五步:检查资源
free -h df -h df -i uptime |
第六步:检查后端日志
journalctl -u 后端服务名称 -n 100 --no-pager |
第七步:验证配置
nginx -t |
第八步:平滑重新加载
systemctl reload nginx |
十八、常见错误处理对照表
| 现象 | 优先检查 | 常见处理方向 |
|---|---|---|
| 所有PHP页面502 | PHP-FPM状态 | 启动服务并检查退出原因 |
| 静态文件正常、动态页面502 | FastCGI配置 | 对比Socket或端口 |
Connection refused | 后端监听端口 | 启动应用或修正端口 |
No such file | Unix Socket路径 | 修正Nginx与PHP-FPM配置 |
Permission denied | Socket权限、SELinux | 修正用户、组及安全策略 |
upstream timed out | 应用和数据库性能 | 查慢请求,再评估超时设置 |
| 高峰期出现502 | CPU、内存、进程池 | 优化应用并评估容量 |
| 容器应用502 | 容器状态和端口映射 | 查容器日志与监听地址 |
| 删除或升级PHP后502 | 服务名和Socket变化 | 更新Nginx的FastCGI地址 |
too big header | Cookie和响应头 | 修复异常响应,再调整缓冲区 |
十九、如何减少502再次发生
修复故障后,可以采取以下措施:
- 为Nginx、PHP-FPM和应用配置日志轮换;
- 监控CPU、内存、磁盘和inode;
- 监控后端端口和健康检查接口;
- 记录PHP-FPM进程池使用情况;
- 为应用配置慢请求和慢查询日志;
- 对数据库和第三方接口设置合理超时;
- 使用进程管理器自动恢复异常应用;
- 更新PHP或部署新版本后检查Socket路径;
- 在上线前执行Nginx配置检查;
- 对重要业务准备回滚方案;
- 在多节点架构中避免所有实例同时重启。
监控告警应尽量早于用户发现故障。例如,可以在后端健康检查失败、PHP-FPM进程接近上限或服务器内存持续不足时提前通知。
总结
Nginx出现502 Bad Gateway,通常是Nginx与后端服务之间的通信发生异常。
最有效的排查路径是:
确认故障范围 → 检查Nginx状态 → 查看Nginx错误日志 → 检查PHP-FPM或后端应用 → 对比Socket及端口 → 检查权限和SELinux → 检查CPU、内存、磁盘 → 分析应用与数据库性能 → 验证配置并重新加载 |
遇到502时,重启服务可能暂时恢复访问,但日志才能说明真正原因。只有根据错误信息修复监听地址、权限、资源不足或应用阻塞等根因,才能避免故障反复出现。
参考资料
- Nginx官方文档:FastCGI模块
- Nginx官方文档:HTTP Proxy模块
- Nginx官方文档:请求处理方式
- PHP官方手册:PHP-FPM配置
- systemd官方手册:journalctl




