Nginx 502/504 错误排查与解决方案

一、错误概述

502 Bad Gateway

表示 Nginx 作为反向代理时,上游服务器(如 PHP-FPM、Node.js、Java 应用等)返回了无效响应或连接被拒绝。

504 Gateway Timeout

表示 Nginx 作为反向代理时,上游服务器在指定时间内未能返回响应,导致超时。

二、常见原因分析

502 错误常见原因

原因 说明
上游服务未启动 PHP-FPM、Gunicorn、uWSGI 等服务进程未运行
端口/Socket 配置错误 Nginx 配置的上游地址与实际监听地址不匹配
权限问题 Nginx 用户无权访问 Unix Socket 文件
上游服务崩溃 应用进程因错误退出或重启中
防火墙拦截 本地防火墙阻止了 Nginx 与上游服务的通信

504 错误常见原因

原因 说明
上游处理过慢 应用执行复杂查询或计算,超过 proxy_read_timeout
数据库锁等待 后端数据库存在锁竞争,响应延迟
资源耗尽 上游服务器 CPU/内存不足,处理缓慢
网络延迟 跨机房或跨网络调用存在延迟
超时配置过短 Nginx 超时时间设置不合理

三、排查步骤

步骤 1:检查 Nginx 错误日志

1
2
3
4
5
# 查看实时错误日志
tail -f /var/log/nginx/error.log

# 搜索 502/504 相关错误
grep -E "502|504|upstream" /var/log/nginx/error.log | tail -50

典型错误信息:

1
2
3
connect() failed (111: Connection refused) while connecting to upstream
upstream prematurely closed connection while reading response header
upstream timed out (110: Connection timed out) while reading response header

步骤 2:检查上游服务状态

1
2
3
4
5
6
7
8
9
10
11
# PHP-FPM 示例
systemctl status php-fpm
systemctl status php8.1-fpm

# 检查进程监听
ss -tlnp | grep -E "9000|php"
netstat -tlnp | grep -E "9000|php"

# 检查 Unix Socket(如果使用)
ls -la /run/php/
ls -la /var/run/php-fpm/

步骤 3:验证 Nginx 配置

1
2
3
4
5
6
7
8
# 测试配置文件语法
nginx -t

# 查看当前配置
nginx -T | grep -A 10 "upstream\|proxy_pass\|fastcgi_pass"

# 检查 server 块配置
cat /etc/nginx/sites-available/your-site | grep -E "proxy_pass|fastcgi_pass|timeout"

步骤 4:检查权限问题

1
2
3
4
5
6
7
8
9
10
11
# 查看 Socket 文件权限
ls -la /run/php/php-fpm.sock

# Nginx 运行用户
ps aux | grep nginx | head -1

# 如果权限不足,调整 Socket 权限
# 在 php-fpm 配置中设置:
# listen.owner = www-data
# listen.group = www-data
# listen.mode = 0660

步骤 5:检查资源使用情况

1
2
3
4
5
6
7
8
9
# 检查上游服务资源
top -p $(pgrep -f php-fpm)
htop

# 检查内存
free -h

# 检查磁盘 IO
iostat -x 1 5

四、解决方案

方案 1:重启上游服务

1
2
3
4
5
6
7
8
9
# PHP-FPM
systemctl restart php-fpm
systemctl restart php8.1-fpm

# Node.js (PM2)
pm2 restart all

# Python (Gunicorn)
systemctl restart gunicorn

方案 2:调整超时配置

在 Nginx 配置中添加或修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;

# 超时配置
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 300s;
fastcgi_read_timeout 300s;

# 缓冲区配置
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
}

对于反向代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
location / {
proxy_pass http://backend:8080;

# 超时配置
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;

# 重试配置
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 10s;
}

方案 3:优化上游应用

PHP 优化示例:

1
2
3
4
5
6
7
8
9
10
11
12
; php.ini 调整
max_execution_time = 300
max_input_time = 300
memory_limit = 512M

; php-fpm 池配置
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

数据库查询优化:

1
2
3
4
5
6
7
8
9
-- 检查慢查询
SHOW PROCESSLIST;

-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;

-- 分析慢查询
EXPLAIN SELECT * FROM large_table WHERE ...;

方案 4:增加健康检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
upstream backend {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;

# 保持连接
keepalive 32;
}

server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}

方案 5:配置错误页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
http {
# 自定义错误页面
proxy_intercept_errors on;
error_page 502 /502.html;
error_page 504 /504.html;

location = /502.html {
internal;
root /usr/share/nginx/html;
}

location = /504.html {
internal;
root /usr/share/nginx/html;
}
}

五、预防措施

1. 监控告警配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Prometheus 告警规则
groups:
- name: nginx_alerts
rules:
- alert: Nginx502Error
expr: rate(nginx_http_requests_total{status="502"}[5m]) > 0.1
for: 2m
labels:
severity: warning
annotations:
summary: "Nginx 502 错误率过高"

- alert: Nginx504Error
expr: rate(nginx_http_requests_total{status="504"}[5m]) > 0.1
for: 2m
labels:
severity: warning
annotations:
summary: "Nginx 504 超时错误率过高"

2. 日志轮转配置

1
2
3
4
5
6
7
8
9
10
11
# /etc/nginx/nginx.conf
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';

access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
}

3. 定期检查清单

  • 上游服务进程状态正常
  • Socket/端口监听正常
  • 权限配置正确
  • 超时参数合理
  • 资源使用率在安全范围
  • 错误日志无异常增长

六、故障复盘模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
## 故障信息
- 发生时间:YYYY-MM-DD HH:MM
- 影响范围:XX 服务/XX 用户
- 持续时间:XX 分钟

## 故障现象
- 502/504 错误比例:XX%
- 受影响接口:XXX

## 根本原因
- 直接原因:XXX
- 深层原因:XXX

## 处理过程
1. HH:MM 发现告警
2. HH:MM 定位到 XXX 问题
3. HH:MM 执行 XXX 操作
4. HH:MM 服务恢复

## 改进措施
- [ ] 短期:XXX
- [ ] 长期:XXX

七、总结

错误类型 排查重点 常见解决方式
502 Bad Gateway 上游服务状态、连接配置、权限 重启服务、修正配置、调整权限
504 Gateway Timeout 超时配置、应用性能、资源 增加超时、优化应用、扩容资源

核心原则:

  1. 先看日志,定位具体错误信息
  2. 检查上游服务是否正常运行
  3. 验证配置是否正确
  4. 根据业务特点调整超时参数
  5. 建立监控告警,提前发现问题