[AI 生成] Nginx 502 Bad Gateway 排查手册(Python 后端篇)

适用场景

  • Nginx 作为反向代理,后端为 Python Web 应用(Django/Flask/FastAPI 等)

  • 使用 uWSGI 或 Gunicorn 作为 WSGI 服务器

  • 错误日志中出现:502 Bad Gateway,对应的 upstream 为 Python 后端


一、连接与网络层

1.1 后端服务未启动 / 进程崩溃

现象

Nginx error.log:

text

复制代码
connect() failed (111: Connection refused) while connecting to upstream

排查方法

步骤 命令 / 路径 说明
查看后端进程 `ps aux grep -E "uwsgi
检查 systemd 状态 systemctl status your-app.service 适用于 systemd 管理的服务
尝试直接访问后端 curl -v http://127.0.0.1:8080/health 替换为你的后端监听地址和端口
查看后端日志 tail -100 /var/log/uwsgi/app.log journalctl -u your-app -n 50 找到应用级日志路径
手动启动测试 uwsgi --ini /path/to/uwsgi.ini 前台运行,观察是否有错误退出

1.2 端口被占用 / 监听地址错误

现象

后端日志出现:Address already in use

Nginx 无法连接,error.log 可能没有明确错误(但 curl 会失败)

排查方法

步骤 命令 / 路径 说明
查看端口占用 `ss -tlnp grep 8080`
检查监听地址 同上,看是 0.0.0.0:8080 还是 127.0.0.1:8080 Nginx 必须能访问该 IP
查看 uWSGI 配置 `grep -E "socket http-socket" /path/to/uwsgi.ini`
查看 Gunicorn 配置 grep bind /path/to/gunicorn.conf.py bind = '0.0.0.0:8000'
杀掉占用进程后重启 fuser -k 8080/tcp 慎用,会强制结束占用端口的进程

1.3 防火墙 / 安全组拦截

现象

从 Nginx 机器上 telnet 后端IP 后端端口 不通

Nginx error.log:connect() failed (113: No route to host)Connection timed out

排查方法

步骤 命令 / 路径 说明
从 Nginx 机器测试连通性 telnet 10.0.0.2 8080 替换为后端实际 IP 和端口
查看本机防火墙 iptables -L -n -v firewall-cmd --list-all 检查是否有 DROP/REJECT 规则
检查云平台安全组 登录控制台,查看入站规则 必须允许 Nginx 所在机器的 IP 访问后端端口
临时关闭防火墙测试 systemctl stop firewalld(CentOS) ufw disable(Ubuntu) 仅测试,不要长期关闭
查看 SELinux 阻止 ausearch -m avc -ts recent 如果启用 SELinux,可能会拒绝网络连接

1.4 Unix Socket 文件权限错误

现象

Nginx error.log:

connect() to unix:/path/to/uwsgi.sock failed (13: Permission denied)

排查方法

步骤 命令 / 路径 说明
查看 socket 文件权限 ls -l /path/to/uwsgi.sock 例如 srw-rw---- 1 appuser appgroup 0 ...
查看 Nginx 运行用户 `ps aux grep nginx`
修改 socket 文件所属组 chgrp www-data /path/to/uwsgi.sock 将 Nginx 用户加入 socket 组
修改目录权限 chmod 755 /path/to/dir/containing/sock 保证 Nginx 用户能进入目录
在 uWSGI 配置中指定用户/组 uid = www-data gid = www-data chmod-socket = 660 启动时自动设置权限

1.5 Nginx 与后端网络不通

现象

Nginx error.log:connect() failed (110: Connection timed out)

排查方法

步骤 命令 / 路径 说明
测试基础连通性 ping 后端IP 确认网络层可达
路由跟踪 traceroute 后端IP 查看经过的跳数,确定哪里阻断
检查跨主机部署时端口映射 docker psnetstat -tlnp 在容器宿主机上 确认 Docker bridge 或 host 模式端口正确暴露

二、应用服务器层(uWSGI / Gunicorn)

2.1 监听队列已满(listen queue full)

现象

uWSGI 日志出现:

uWSGI listen queue of socket "0.0.0.0:8181" (fd: 3) full !!! (513/512)

Nginx 可能报:upstream timed out (110: Connection timed out)connect() to ... failed (11: Resource temporarily unavailable)

排查方法

步骤 命令 / 路径 说明
查看 uWSGI 日志 grep "listen queue" /var/log/uwsgi/*.log 确认队列溢出频率
查看当前队列大小 curl http://127.0.0.1:1717/(stats 服务) 或 uwsgi --connect-and-read /tmp/stats.sock 需提前开启 stats 端口
查看系统 backlog `ss -lnt grep 8181`
查看系统限制 sysctl net.core.somaxconn 默认为 128,uWSGI 的实际上限不会超过它
临时提高系统限制 sysctl -w net.core.somaxconn=65536 立即生效,重启失效
永久修改 编辑 /etc/sysctl.conf,添加 net.core.somaxconn=65536,执行 sysctl -p 持久化配置
调整 uWSGI listen 编辑 uwsgi.ini:listen = 1024 重启服务生效
增加 worker 数量 processes = 8(或更多) 提高并发处理能力,减少队列堆积

2.2 Worker 全部忙碌(无空闲进程)

现象

请求响应变慢,Nginx 报 upstream timed out (110: Connection timed out),后端 CPU 占用很高

排查方法

步骤 命令 / 路径 说明
查看 uWSGI stats curl http://127.0.0.1:1717/ 观察 "workers""requests""status":"busy" 若所有 worker 的 busy 数量等于 processes 数,则表示满负荷
查看系统负载 tophtop,按 H 显示线程 确认 CPU 是否耗尽
查看每个 worker 状态 uwsgi --connect-and-read /tmp/stats.sock 返回 JSON 或安装 uwsgitop 工具
增加 worker 数量 processes = 16(uWSGI) workers = 9(Gunicorn) 一般建议 2*CPU核数+1,需监控内存
启用线程(混合模式) threads = 4(每个进程开 4 个线程) 可提高并发,但注意 GIL

2.3 Worker 意外崩溃 / 频繁重启

现象

Nginx error.log:upstream prematurely closed connection while reading response header from upstream

uWSGI 日志中出现:DAMN ! worker ... diedrespawn 字样

排查方法

步骤 命令 / 路径 说明
查看 uWSGI 日志上下文 tail -200 /var/log/uwsgi/app.log 找到 worker 死亡前的最后几行
检查应用日志 tail -100 /var/log/app/app.log 看是否有未捕获异常导致进程退出
检查 harakiri 超时 grep harakiri /etc/uwsgi/*.ini 若设置 harakiri = 30,超过 30 秒无响应的请求会被强制杀掉 worker
检查 max-requests max-requests = 1000 worker 处理 1000 个请求后重启,有可能在重启瞬间少量 502
查看系统 OOM `dmesg -T grep -i "oom"`
开启 uWSGI 内存报告 log-master = true log-drain = true memory-report = true 可在日志中看到每个 worker 的内存占用

2.4 uWSGI 缓冲区过小

现象

Nginx error.log:upstream sent too big header while reading response header from upstream

uWSGI 日志:invalid request block size: ...

排查方法

步骤 命令 / 路径 说明
查看当前 buffer-size grep buffer-size /path/to/uwsgi.ini 默认 4096 (4KB)
临时调大测试 buffer-size = 32768 重启 uWSGI 后观察
检查响应头或 Cookie 大小 在应用代码中打印 len(response_headers) 大 Cookie、JWT 可能导致超限
同时调整 Nginx 缓冲区 proxy_buffer_size 16k; proxy_buffers 4 16k; 在 Nginx locationhttp 块中配置

2.5 Gunicorn 超时设置

现象

Gunicorn 日志:[CRITICAL] WORKER TIMEOUT,然后 worker 被 kill,Nginx 收到连接关闭

排查方法

步骤 命令 / 路径 说明
查看 Gunicorn 配置 grep timeout /path/to/gunicorn.conf.py 默认 30 秒
增加超时时间 timeout = 120 如果应用确实需要长时间处理,可调大
优化代码减少耗时 使用 cProfilepy-spy 定位慢函数 从根源解决
查看 Gunicorn 日志 journalctl -u gunicorn -n 50 systemd 下的日志

2.6 uWSGI harakiri 超时触发

现象

uWSGI 日志:HARAKIRI: worker 1 (pid:12345) is taking too much time (over 30 seconds),随后 DAMN ! worker 1 died

排查方法

步骤 命令 / 路径 说明
查看 harakiri 值 grep harakiri /etc/uwsgi/*.ini 默认未开启
临时关闭 harakiri 测试 注释掉配置行 若问题消失,说明业务确实耗时超过阈值
调大 harakiri harakiri = 120 给慢请求更多时间
优化代码 使用异步、缓存、消息队列 避免同步阻塞

三、Python 应用代码层

3.1 未捕获的异常导致 worker 退出

现象

Worker 突然消失,Nginx 502,应用日志有完整 traceback

排查方法

步骤 命令 / 路径 说明
查看应用日志 tail -100 /var/log/app/app.log 寻找 Traceback (most recent call last)
检查全局异常处理 查看 app.errorhandler(500) 或 middleware 确保不会让 worker 崩溃
添加日志记录所有异常 使用 logging.exception(e)except 块中 方便定位
使用 Sentry / 其他错误追踪 集成 sentry-sdk 自动收集未捕获异常

3.2 死锁 / 长时间阻塞

现象

所有 worker 逐步卡住,请求超时,CPU 可能不高(线程阻塞等待 I/O)

排查方法

步骤 命令 / 路径 说明
查看 uWSGI stats curl 127.0.0.1:1717 查看每个 worker 的 "status""avg_rt" 若所有 worker 都处于 busy 状态且平均响应时间很长,说明阻塞
使用 py-spy 查看调用栈 pip install py-spy py-spy dump --pid <worker_pid> 查看卡在哪个函数
使用 strace 跟踪系统调用 strace -p <worker_pid> -e trace=network,read,write 看是否卡在 recv/send
检查数据库连接池 查看数据库连接池配置 max_overflow, pool_size 若连接耗尽会阻塞
检查外部 API curl -w "time_total:%{time_total}" 测试外部服务 确认没有慢调用
添加代码超时控制 使用 timeout_decoratorasyncio.wait_for 防止无限阻塞

3.3 响应 Content-Length 与实际不符

现象

Nginx error.log:upstream sent invalid header: "Content-Length: 100" while reading response header from upstream

排查方法

步骤 命令 / 路径 说明
用 curl 查看响应头 curl -i http://backend:port/some/url 观察 Content-Length 与实际 body 长度是否一致
检查应用代码 搜索 Content-Length 头部设置 可能手动设置的错误值
检查中间件 某些压缩中间件可能错误修改 Content-Length 禁用 gzip 测试
使用 Wireshark 抓包 tcpdump -i lo -s 0 -A port 8080 精确分析响应

现象

Nginx error.log:upstream sent too big header while reading response header from upstream

排查方法

步骤 命令 / 路径 说明
查看 Nginx 缓冲区当前大小 grep proxy_buffer /etc/nginx/nginx.conf 默认 4k/8k
临时增大缓冲区 proxy_buffer_size 16k; proxy_buffers 8 16k; 重启 Nginx
检查 Cookie 大小 `curl -sI http://backend:port grep -i set-cookie`
优化 Cookie 存储 使用服务器端 session,或压缩信息 避免存入大量 JSON
检查 JWT token 大小 解码后查看 payload 大小 避免存入过多自定义字段

3.5 应用内部死循环 / 内存泄漏

现象

Worker 内存持续增长,最终被 OOM Killer 杀掉,Nginx 502

排查方法

步骤 命令 / 路径 说明
查看内存趋势 top -p <worker_pid> 并持续观察 RES 若一直上升,疑似泄漏
使用 memory-profiler 在代码中插入 @profile 并运行 python -m memory_profiler script.py 定位泄漏点
检查全局变量 查看是否有不断增长的 list/dict 未清理 常见于缓存未设置上限
启用 uWSGI memory-report memory-report = true 日志中每个 worker 的内存使用
重启 worker 策略 max-requests = 2000 定期回收,缓解泄漏影响

四、资源限制层

4.1 文件描述符不足

现象

uWSGI log:accept4() failed: Too many open files

Nginx log:socket() failed (24: Too many open files)

排查方法

步骤 命令 / 路径 说明
查看当前限制 ulimit -n 软限制,默认 1024 较低
查看进程已打开 fd 数量 `lsof -p wc -l`
临时提高限制 ulimit -n 65535 仅当前 shell 有效
永久修改(systemd) 在 service 文件中加 LimitNOFILE=65535 然后 systemctl daemon-reload
永久修改(limits.conf) 编辑 /etc/security/limits.conf,添加: * soft nofile 65535 * hard nofile 65535 重启后生效
检查 socket 泄漏 `lsof -p grep sock`

4.2 内存不足(OOM Killer)

现象

后端进程突然消失,dmesg -T | grep -i oom 有记录

排查方法

步骤 命令 / 路径 说明
查看系统内存 free -h 观察 available 内存
查看 OOM 日志 `dmesg -T grep -i "killed process"`
检查后端内存设置 uWSGI 的 limit-as 限制 可能设置过小
增加内存或 swap dd if=/dev/zero of=/swapfile bs=1M count=2048 && mkswap && swapon 临时缓解
优化代码内存占用 使用 tracemallocmemory_profiler 找出内存消耗大的对象
调整 OOM 分数 echo -1000 > /proc/<pid>/oom_score_adj 防止重要进程被杀(不推荐)

4.3 CPU 限制(容器环境)

现象

应用整体响应慢,队列堆积,超时 502,docker stats 显示 CPU 达到上限

排查方法

步骤 命令 / 路径 说明
查看容器资源限制 `docker inspect <container_id> grep -A5 "CpuQuota"`
查看容器 CPU 使用 docker stats <container> 看到 % 接近 limit
增加 CPU 配额 docker update --cpus=2 <container> 运行时调整(需支持)
调整 Kubernetes requests/limits 编辑 deployment yaml:resources: limits: cpu: "2" kubectl apply -f
优化应用计算密集部分 使用 cProfile 分析性能瓶颈 减少不必要的计算

4.4 线程数限制

现象

uWSGI 日志:can't create thread,Nginx 502

排查方法

步骤 命令 / 路径 说明
查看系统最大线程数 cat /proc/sys/kernel/threads-max 通常很大
查看用户进程限制 ulimit -u 默认一般 4096 或更多
检查 uWSGI 线程数 threads = 2processes = 10,总线程数 = 20 应该远低于限制
提高 ulimit -u 在 limits.conf 中:* soft nproc 65535 重启
排查线程泄漏 使用 `ps -eLf grep uwsgi

五、Nginx 与后端协议配置不一致

5.1 HTTP 版本不匹配 + Keep-Alive 冲突

现象

典型的你遇到的场景:后端期望 HTTP/1.1 并复用连接,但 Nginx 默认使用 HTTP/1.0 且关闭 keep-alive,导致后端 reset 连接,Nginx 502

排查方法

步骤 命令 / 路径 说明
查看 Nginx 配置 grep -A5 "proxy_pass" /etc/nginx/sites-enabled/default 确认是否有 proxy_http_version
添加兼容配置 在 location 块中加入: proxy_http_version 1.1; proxy_set_header Connection ""; 使 Nginx 与后端间使用 HTTP/1.1 长连接
检查后端 keep-alive 设置 uWSGI:http-keepalive = 1 Gunicorn:keepalive = 5 确认后端已启用

5.2 Nginx 使用 uwsgi_pass 但后端是 HTTP 协议

现象

直接 502,没有明确错误;后端日志无任何访问记录

排查方法

步骤 命令 / 路径 说明
查看 Nginx 配置 grep "uwsgi_pass" /etc/nginx/conf.d/ 如果用了 uwsgi_pass,后端必须使用 uWSGI 协议(socket 而不是 http-socket
检查 uWSGI 协议 后端 uWSGI 配置中必须是 socket = 0.0.0.0:3031,而不是 http-socket uwsgi 协议比 HTTP 更高效
如果要使用 HTTP 协议 Nginx 改用 proxy_pass http://backend:port 同时后端应使用 http-socket 或直接是 Gunicorn HTTP 监听

5.3 upstream 中 server 为域名且解析失败

现象

Nginx 启动时 warn 或 reload 后 502,但后端明明在运行

排查方法

步骤 命令 / 路径 说明
检查 upstream 配置 grep -A2 "upstream" /etc/nginx/conf.d/ 看 server 用的是 IP 还是域名
测试域名解析 nslookup backend.local 确保解析正常
使用 IP 代替域名 直接写 server 10.0.0.2:8080 避免 DNS 解析问题
配置 resolver 在 nginx.conf 中加: resolver 8.8.8.8 valid=30s; 适用于动态 upstream

5.4 后端的 backlog 与 Nginx 的队列冲突

现象

突发流量时少量 502,平时正常

排查方法

步骤 命令 / 路径 说明
查看系统 backlog 使用 `ss -lnt grep :8080`
提高 Nginx 的 proxy_connect_timeout proxy_connect_timeout 5s; 给后端更多时间建立连接
协调 uWSGI listen 与 Nginx 超时 listen = 1024 proxy_connect_timeout 3s 确保队列不会过早塞满

六、综合排查脚本

将以下脚本保存为 debug_502.sh,遇到 502 时快速收集现场:

bash

复制代码
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
OUTDIR="/tmp/502_debug_$DATE"
mkdir -p "$OUTDIR"

# 1. Nginx 错误日志
tail -50 /var/log/nginx/error.log > "$OUTDIR/nginx_error.log"

# 2. 后端日志(根据实际修改路径)
tail -50 /var/log/uwsgi/app.log > "$OUTDIR/uwsgi.log" 2>/dev/null
tail -50 /var/log/gunicorn/access.log > "$OUTDIR/gunicorn.log" 2>/dev/null
journalctl -u your-app -n 50 > "$OUTDIR/systemd.log" 2>/dev/null

# 3. 进程状态
ps aux | grep -E "uwsgi|gunicorn|python" > "$OUTDIR/ps.txt"

# 4. 端口监听
ss -tlnp > "$OUTDIR/ss_tlnp.txt"

# 5. 队列状态(假设后端端口 8181)
ss -lnt | grep :8181 > "$OUTDIR/queue_status.txt"

# 6. 系统限制
ulimit -a > "$OUTDIR/ulimit.txt"
sysctl net.core.somaxconn > "$OUTDIR/somaxconn.txt"
cat /proc/sys/fs/file-max > "$OUTDIR/file_max.txt"

# 7. 内存使用
free -h > "$OUTDIR/free_h.txt"
dmesg -T | grep -i "oom" > "$OUTDIR/oom.txt" 2>/dev/null

echo "Debug info collected in $OUTDIR"
tar -czf "$OUTDIR.tar.gz" "$OUTDIR"
echo "Compressed archive: $OUTDIR.tar.gz"

附录:常用配置速查

uWSGI 生产推荐配置片段

ini

复制代码
[uwsgi]
socket = 0.0.0.0:8181
processes = 8
threads = 2
listen = 1024
buffer-size = 32768
harakiri = 60
max-requests = 2000
memory-report = true
log-master = true

Nginx 反向代理配置片段

nginx

复制代码
location / {
    proxy_pass http://backend_upstream;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    
    proxy_connect_timeout 5s;
    proxy_read_timeout 60s;
    proxy_send_timeout 60s;
    
    proxy_buffer_size 16k;
    proxy_buffers 8 16k;
}
相关推荐
小马爱打代码1 小时前
SpringBoot + SpringCloud Gateway + Sentinel + Redis:API 网关层的接口限流、黑名单拦截与用户认证
spring boot·spring cloud·gateway
Anthony_2311 小时前
Linux 从基础操作到故障排查
linux·运维·服务器·网络·nginx·ubuntu·centos
莫宰特1 小时前
NNMind:像搭积木一样设计神经网络
人工智能·python·深度学习·从零训练
Wonderful U1 小时前
基于Python+Django的轻量化私有云盘系统:从零搭建安全可控的文件存储与共享平台
python·安全·django
garmin Chen1 小时前
Prompt工程入门:让AI按你的要求工作(1)--prompt概述与设计
java·人工智能·python·junit·prompt·agent
imDwAaY1 小时前
从感知机到 Attention:我用 PyTorch 打穿 CS188 机器学习终章 CS188 Proj5 学习笔记
人工智能·pytorch·笔记·python·学习·机器学习
lifloveyou10 小时前
table接口结构
python
Warson_L12 小时前
class 扩展
python
前端与小赵13 小时前
Python 数据结构陷阱与复数运算优化:列表、元组、字典成员操作辨析及 NumPy 高效实践
python