Nginx 报 502、504、连接超时,看起来都是“请求没成功”,但根因完全不是一类问题。502 更多是上游服务直接返回无效响应、连接被拒绝或进程挂了;504 更像是请求已经到上游,但超时窗口内没处理完;连接超时则要分清楚是客户端连不到 Nginx,还是 Nginx 连不上 upstream,还是三次握手卡在内核队列里。
线上处理这类问题,最忌讳拿着错误码直接拍脑袋。我的习惯是先把路径拆成四段:客户端 -> Nginx -> upstream -> 内核/网络。只要能定位出哪一段开始失败,排障速度会快很多。
一、概述
1.1 背景介绍
Nginx 是很多业务的入口层和反向代理层,一旦出现 502、504 或连接超时,业务侧感知通常很直接:
网关返回 5xx,接口成功率快速下降
页面首屏打开慢,静态资源加载卡住
上游服务监控看起来还活着,但外部流量已经受影响
这篇手册解决的是三类高频问题:
Nginx 为何会报 502,常见故障点在哪
504 和 upstream 超时要从哪些配置和指标入手
连接超时到底是连接数、backlog、网络还是服务端处理慢
1.2 技术特点
按链路拆解:把一个错误码拆成监听层、代理层、上游层、内核层四个检查点
日志和连接状态联动:错误日志、访问日志、ss/netstat、应用日志同时看,避免单点误判
面向生产修复:不只给“怎么看”,还给“怎么止血、怎么回滚、怎么预防”
1.3 适用场景
业务网关、API 网关、反向代理层出现 502/504 告警
静态资源服务、Web 接入层、Kubernetes Ingress Nginx 出现突发超时
微服务架构中 Nginx 代理 Java、Go、PHP-FPM、Node.js upstream 时故障频发
1.4 环境要求
| 组件 | 版本要求 | 说明 |
|---|---|---|
| 操作系统 | CentOS 7/8、Rocky Linux 8/9、Ubuntu 20.04+ | 命令覆盖主流生产环境 |
| Nginx | 1.18+ 或 OpenResty 1.19+ | 文中参数以常用稳定版本为准 |
| 上游服务 | HTTP、FastCGI、uWSGI、gRPC | 案例主要以 HTTP upstream 和 PHP-FPM 为例 |
| 诊断工具 | ss 、curl、tcpdump、ngxtop、strace | 用于连接、日志和抓包定位 |
二、详细步骤
2.1 准备工作
2.1.1 系统检查
先确认是“真的大面积失败”,还是健康检查、个别 URI 或个别 upstream 节点异常。第一轮命令我一般这么打:
date hostname -f nginx -V nginx -t systemctl status nginx --no-pager ss -lntp | grep ':80|:443' ss -s curl -I -m 3 http://127.0.0.1/ tail -n 50 /var/log/nginx/error.log tail -n 50 /var/log/nginx/access.log
第一轮要回答五个问题:
Nginx 进程是不是活着,配置有没有语法问题
错误码主要是 502、504 还是连接超时
是所有站点都异常,还是某个 server/location 异常
是所有 upstream 都失败,还是个别节点失败
错误发生时连接数、重传、backlog 有没有异常
常见日志关键词要先扫一遍:
grep -E "connect() failed|upstream timed out|no live upstreams|recv() failed|connection refused|broken pipe|reset by peer" /var/log/nginx/error.log | tail -100
这些关键词基本能把故障定到某一层:
connect() failed (111: Connection refused):上游没监听、进程挂了、防火墙拦了
upstream timed out (110: Connection timed out):请求到上游了,但在超时窗口内没处理完
no live upstreams:upstream 全部不可用,通常是健康检查或全部失败
recv() failed (104: Connection reset by peer):上游主动断开连接
2.1.2 安装依赖
# Debian / Ubuntu sudo apt update sudo apt install -y curl tcpdump ngrep apache2-utils jq lsof dnsutils # RHEL / CentOS / Rocky sudo yum install -y curl tcpdump ngrep httpd-tools jq lsof bind-utils
如果机器没装 stub_status 或 Prometheus Exporter,排障时信息会少很多。生产环境建议默认开一个只内网可访问的状态页。
2.2 核心配置与排查步骤
2.2.1 第一步:把错误定位到哪一段链路
这一步先区分是客户端到 Nginx、Nginx 到 upstream、还是 upstream 内部处理超时。
curl -sS -o /dev/null -w 'code=%{http_code} connect=%{time_connect} start=%{time_starttransfer} total=%{time_total}
' http://127.0.0.1/api/health
curl -sS -o /dev/null -w 'code=%{http_code} connect=%{time_connect} start=%{time_starttransfer} total=%{time_total}
' http://:/health
ss -ant state syn-recv
ss -ant state time-wait | wc -l
判断思路:
本机访问 Nginx 正常,但外部访问超时:优先查防火墙、L4 负载均衡、证书、网络 ACL
本机访问 Nginx 502,直连 upstream 也失败:问题在 upstream
本机访问 Nginx 504,直连 upstream 响应慢:问题在 upstream 处理时长
本机访问 Nginx 慢,直连 upstream 正常:问题多半在 Nginx 配置、DNS、连接复用或内核连接队列
2.2.2 第二步:检查 upstream 配置和超时参数
Nginx 排障时,配置不能只看有没有写错,还要看值是不是符合业务流量模型。下面这几个参数最常出事故:
upstream order_service {
least_conn;
server 10.10.20.31:8080 max_fails=3 fail_timeout=10s;
server 10.10.20.32:8080 max_fails=3 fail_timeout=10s;
keepalive 128;
}
server {
listen 80 reuseport backlog=65535;
server_name api.example.com;
access_log /var/log/nginx/api.access.log main_ext;
error_log /var/log/nginx/api.error.log warn;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 2s;
proxy_send_timeout 10s;
proxy_read_timeout 15s;
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_tries 2;
proxy_pass http://order_service;
}
}
关键参数解释:
proxy_connect_timeout:Nginx 连 upstream 的时间,不建议无脑拉大
proxy_read_timeout:Nginx 等待 upstream 响应的时间,和业务接口 SLA 强相关
keepalive:upstream 长连接池大小,过小会增加建连成本,过大又会压上游连接数
backlog:监听队列长度,流量突发时太小容易丢连接
proxy_next_upstream_tries:失败重试次数,设太大可能放大雪崩
生产环境里,超时参数最好分接口类型配置,不要全站统一一个值。支付回调、导出任务、普通查询接口的超时窗口本来就不该一样。
2.2.3 第三步:结合错误日志定位 502、504、超时模式
错误日志是这类故障的核心证据。下面这组命令建议固定成模板:
tail -f /var/log/nginx/error.log
grep -E " 502 | 504 " /var/log/nginx/access.log | tail -50
awk '$9 ~ /502|504/ {print $4,$5,$7,$9,$10,$11}' /var/log/nginx/access.log | tail -50
grep -E "connect() failed|upstream timed out|reset by peer|no live upstreams" /var/log/nginx/error.log | tail -100
我一般按下面方式定性:
502 + connection refused:upstream 端口没监听、进程挂了、容器未就绪
502 + reset by peer:上游主动断开,常见于上游线程池满、进程崩溃、FD 打满
504 + upstream timed out:上游还活着,但处理不过来,可能是慢 SQL、锁等待、外部依赖阻塞
客户端连接超时:要查 worker_connections、backlog、系统连接队列、SYN flood、L4 转发路径
2.3 启动和验证
2.3.1 重新加载配置
排查过程中经常需要临时打开更详细日志或调高某个接口超时。改配置前先做语法检查和备份。
sudo cp -a /etc/nginx /etc/nginx.$(date +%F_%H%M%S).bak sudo nginx -t sudo nginx -s reload sudo systemctl status nginx --no-pager
如果是高峰期,优先做最小化修改,不要顺手一起改 upstream 策略、缓存策略和 gzip 参数,容易把故障面扩大。
2.3.2 功能验证
# 验证命令
curl -sS -o /dev/null -w 'code=%{http_code} connect=%{time_connect} start=%{time_starttransfer} total=%{time_total}
' http://127.0.0.1/api/ping
ab -n 500 -c 50 http://127.0.0.1/api/ping
# 预期输出
# code=200 connect<0.01 start<0.1 total<0.2
验证时不要只看 HTTP 200。还要同时看:
error.log 是否还在刷 502/504
upstream 实例错误率是否同步下降
ss -s 中 estab/syn-recv/time-wait 是否回到正常区间
三、示例代码和配置
3.1 完整配置示例
3.1.1 主配置文件
下面这份配置适合生产网关场景,重点是把日志字段打全,并给 upstream 长连接、超时和失败重试一个稳妥基线。
# 文件路径:/etc/nginx/conf.d/api_gateway.conf
log_format main_ext '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'rt=$request_time urt=$upstream_response_time '
'uaddr=$upstream_addr ustatus=$upstream_status '
'xff="$http_x_forwarded_for" host="$host" '
'reqid="$request_id"';
upstream api_backend {
least_conn;
keepalive 256;
server 10.10.30.21:8080 max_fails=3 fail_timeout=10s;
server 10.10.30.22:8080 max_fails=3 fail_timeout=10s;
server 10.10.30.23:8080 backup;
}
server {
listen 80 reuseport backlog=65535;
server_name api.example.com;
access_log /var/log/nginx/api.access.log main_ext;
error_log /var/log/nginx/api.error.log warn;
client_header_timeout 10s;
client_body_timeout 15s;
keepalive_timeout 30s;
keepalive_requests 1000;
send_timeout 10s;
location /nginx_status {
stub_status;
allow 127.0.0.1;
allow 10.10.0.0/16;
deny all;
}
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Request-Id $request_id;
proxy_connect_timeout 2s;
proxy_send_timeout 10s;
proxy_read_timeout 15s;
proxy_buffering on;
proxy_buffers 16 32k;
proxy_busy_buffers_size 128k;
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_tries 2;
proxy_pass http://api_backend;
}
}
这份配置里最有价值的是两点:
access_log 里把 request_time、upstream_response_time、upstream_addr、upstream_status 全打出来,定位 502/504 时能直接看出是哪台 upstream 出问题
proxy_next_upstream_tries 只设 2,避免 upstream 已经慢死了,Nginx 还继续重试放大压力
3.1.2 辅助脚本
这份脚本用于快速统计最近 5 分钟的 502、504 和连接失败日志,值班时很实用,不用每次都手敲 awk。
#!/usr/bin/env bash
# 文件名:/usr/local/bin/nginx_5xx_report.sh
# 功能:统计 Nginx 近 5 分钟 502/504/超时情况,并输出热点 upstream
set -euo pipefail
ACCESS_LOG="/var/log/nginx/api.access.log"
ERROR_LOG="/var/log/nginx/api.error.log"
START_TS="$(date -d '5 minutes ago' '+%d/%b/%Y:%H:%M')"
echo "== 近 5 分钟 access 日志中的 5xx 统计 =="
awk -v start="$START_TS" '
index($4, start) || seen {
seen=1
if ($9 ~ /^50[24]$/) {
total[$9]++
upstream[$0]++
}
}
END {
for (code in total) {
printf "%s => %d
", code, total[code]
}
}' "$ACCESS_LOG"
echo
echo "== 最近 100 条错误日志中的热点错误 =="
tail -100 "$ERROR_LOG" |
egrep 'connect() failed|upstream timed out|reset by peer|no live upstreams' |
sort | uniq -c | sort -nr
echo
echo "== 当前连接概览 =="
ss -s
echo
echo "== 当前 nginx status =="
curl -s http://127.0.0.1/nginx_status || true
部署建议:
sudo install -o root -g root -m 0750 nginx_5xx_report.sh /usr/local/bin/nginx_5xx_report.sh
3.2 实际应用案例
案例一:502 原因是 upstream 进程异常退出
场景描述:支付网关突然出现大量 502,错误率从 0.02% 拉到 6% 左右。Nginx 本身 CPU 和内存都正常,外部流量也没有异常放大。
排查过程:
grep " 502 " /var/log/nginx/api.access.log | tail -20 grep "connect() failed" /var/log/nginx/api.error.log | tail -20 ss -lntp | grep 8080 systemctl status pay-service --no-pager journalctl -u pay-service -S -10min
关键现象:
error.log 中大量出现 connect() failed (111: Connection refused) while connecting to upstream
8080 端口监听间歇性消失
上游服务日志显示 JVM 被 OOM Killer 杀掉
实现代码:
grep -E "OutOfMemoryError|Killed process" /var/log/messages /var/log/syslog /var/log/pay-service/app.log
处理动作:
先把故障 upstream 从负载均衡摘掉
拉起服务,确认端口恢复监听
限制异常流量,防止恢复后再次被打挂
追加 JVM 堆、连接池和线程池监控
运行结果:
处理前:502 错误率 6.1%,支付回调积压 1.8 万条 处理后:5 分钟内 502 降到 0.05%,回调堆积逐步消化
案例二:504 根因是慢 SQL 拖垮 upstream
场景描述:营销活动开始后,商品查询接口连续出现 504。Nginx 的 proxy_read_timeout 设为 15 秒,业务方第一反应是把超时改成 60 秒。
这个方向是错的。超时拉长只会让连接占得更久,雪崩来得更快。
排查过程:
grep "upstream timed out" /var/log/nginx/api.error.log | tail -20
awk '$9 == 504 {print $7,$9,$11,$12}' /var/log/nginx/api.access.log | tail -20
curl -sS -o /dev/null -w 'code=%{http_code} total=%{time_total}
' http://10.10.30.21:8080/api/product/list
mysql -e "show full processlist;"
mysql -e "show engine innodb statusG" | egrep -i 'lock wait|wait'
关键现象:
Nginx 错误日志明确提示 upstream timed out
upstream 直连同样慢,响应时间 18-25 秒
数据库里出现多条全表扫描慢 SQL,锁等待时间长
实现步骤:
先对活动接口做限流,保护连接池
在数据库侧杀掉异常慢 SQL
紧急加索引并回滚有问题的查询逻辑
恢复后把 upstream_response_time 和慢 SQL 告警联动
运行结果:
处理前:504 错误率 12.4%,接口 P99 22.7s 处理后:接口 P99 回落到 320ms,504 基本清零
四、最佳实践和注意事项
4.1 最佳实践
4.1.1 性能优化
优化点一:日志字段一次打全,故障时少走弯路
没有 upstream_response_time、upstream_status、upstream_addr 的访问日志,排 502/504 基本只能靠猜。日志量会变大,但这个成本远低于故障期间盲查。
sudo nginx -t sudo nginx -s reload
优化点二:上游连接池和超时按业务类型拆分
同一个 proxy_read_timeout 套所有接口,迟早要踩坑。支付、搜索、导出、上传这几类接口处理时长差异很大,应该拆 location 或拆独立域名配置。
location /api/export/ {
proxy_read_timeout 60s;
proxy_pass http://export_backend;
}
优化点三:避免失败重试放大雪崩
上游已经慢了,再让 Nginx 多次重试,会把连接、线程、数据库压力一起放大。实测下来,高峰期 proxy_next_upstream_tries 大于 2 的配置经常会让故障扩散得更快。
4.1.2 安全加固
安全措施一:状态页只允许内网访问
stub_status 很好用,但别直接暴露到公网。
location /nginx_status {
stub_status;
allow 127.0.0.1;
allow 10.10.0.0/16;
deny all;
}
安全措施二:限制大请求和慢客户端
很多连接超时并不是 upstream 慢,而是慢客户端一直占着连接不放。可以通过请求体大小、头部超时和发送超时做约束。
client_max_body_size 20m; client_header_timeout 10s; client_body_timeout 15s; send_timeout 10s;
安全措施三:对 reload 和配置变更做审计
Nginx 故障很多发生在发布后或临时调整后。把 nginx.conf、conf.d/ 目录和 reload 操作纳入审计,比事后追人靠谱。
4.1.3 高可用配置
HA 方案一:upstream 至少保留 2 个可用节点,关键接口保留 1 个 backup 节点
HA 方案二:入口层做多机房或多可用区部署,避免单点网关故障
备份策略:每次变更前归档 /etc/nginx,并记录 reload 时间点、变更单号和负责人
sudo tar czf /var/backups/nginx-$(date +%F_%H%M%S).tar.gz /etc/nginx
4.2 注意事项
4.2.1 配置注意事项
警告:出现 504 时不要第一反应拉大 proxy_read_timeout。如果根因是 upstream 卡住、数据库慢、锁等待,拉长超时只会让连接占用时间更长,入口层更容易被拖死。
注意事项一:worker_connections 不等于最大并发数,实际还受 worker_processes、文件描述符和 upstream 连接数限制
注意事项二:keepalive_timeout 设太长会占住连接,设太短又会增加频繁建连开销,要结合客户端类型调
注意事项三:proxy_buffering 关闭后排障更直观,但高流量下会增加 upstream 压力,不要高峰期随便改
4.2.2 常见错误
| 错误现象 | 原因分析 | 解决方案 |
|---|---|---|
| 504 一出现就把超时参数翻倍 | 没确认 upstream 真实处理时长 | 先直连 upstream,看数据库、线程池、依赖服务 |
| 502 一出现就重启 Nginx | 问题通常不在 Nginx 主进程 | 先看 error.log,确认是否是 upstream 拒绝连接或重置连接 |
| 连接超时就加机器,不看连接队列 | 可能是 backlog、FD、SYN flood 或防火墙 | 查 ss -s、netstat -s、sysctl 和抓包结果 |
4.2.3 兼容性问题
版本兼容:不同 Nginx/OpenResty 版本对部分模块和日志变量支持不同,升级前先做灰度
平台兼容:容器环境里 worker_processes auto 要结合 CPU limit 看,别按宿主机核数误判
组件依赖:代理 PHP-FPM 时,还要额外检查 fastcgi_* 参数、pm.max_children 和 socket backlog
五、故障排查和监控
5.1 故障排查
5.1.1 日志查看
Nginx 故障排查,日志顺序建议固定成:error.log -> access.log -> upstream 应用日志 -> 系统日志。
# 查看系统日志
sudo journalctl -u nginx -S -30min
# 查看 Nginx 错误日志
tail -f /var/log/nginx/api.error.log
# 查看 502/504 请求
awk '$9 ~ /502|504/ {print $4,$7,$9,$10,$11,$12}' /var/log/nginx/api.access.log | tail -50
如果是 PHP-FPM 或 uWSGI,再补对应日志:
tail -f /var/log/php-fpm/www-error.log tail -f /var/log/uwsgi/app.log
5.1.2 常见问题排查
问题一:大量 502,错误日志提示 connection refused
grep "connect() failed" /var/log/nginx/api.error.log | tail -20 ss -lntp | grep 8080 systemctl status app-service --no-pager
症状:502 激增,upstream 端口偶尔不监听
诊断:上游进程崩溃、未拉起、健康检查未通过或被防火墙拦截
解决:
先摘掉故障 upstream
拉起服务并确认监听恢复
检查 OOM、core、配置错误或启动脚本问题
问题二:大量 504,日志提示 upstream timed out
grep "upstream timed out" /var/log/nginx/api.error.log | tail -20
curl -sS -o /dev/null -w 'code=%{http_code} total=%{time_total}
' http://:/health
症状:接口响应越来越慢,504 比例持续升高
诊断:上游处理时长超出 proxy_read_timeout,根因常在慢 SQL、线程池排队、外部依赖超时
解决:
限流或摘掉最慢接口
查上游应用线程池、GC、数据库、依赖服务
只在确认 SLA 允许时小幅调整超时窗口
问题三:客户端连接超时,但 Nginx error.log 没明显报错
症状:用户连接建立慢或握手失败,Nginx 日志很干净
排查:ss -s、ss -lnt、netstat -s | egrep -i 'listen|overflow|drop|retrans'、抓包看三次握手
解决:检查 somaxconn、tcp_max_syn_backlog、worker_connections、L4 转发和安全设备
5.1.3 调试模式
Nginx 默认错误日志级别不一定够用,排障时可以局部提到 info 或 debug,但不要长时间开全局 debug。
# 临时提升某个站点日志级别 sudo sed -i 's/error_log /var/log/nginx/api.error.log warn;/error_log /var/log/nginx/api.error.log info;/' /etc/nginx/conf.d/api_gateway.conf sudo nginx -t && sudo nginx -s reload # 查看连接和请求状态 curl -s http://127.0.0.1/nginx_status
需要抓包时只抓必要端口和时间窗:
sudo timeout 30 tcpdump -i any -nn hostand port 8080 -w /tmp/nginx_upstream_timeout.pcap
5.2 性能监控
5.2.1 关键指标监控
# 连接状态
ss -s
# Nginx status
curl -s http://127.0.0.1/nginx_status
# 错误码占比
awk '{print $9}' /var/log/nginx/api.access.log | sort | uniq -c | sort -nr | head
# FD 使用
cat /proc/$(cat /run/nginx.pid)/limits | grep "open files"
关键监控项建议包括:
nginx_http_requests_total
nginx_connections_active/reading/writing/waiting
5xx 比例、upstream_response_time 分位数
accepts/handled 差值
主机 TCP 重传、listen overflow、SYN backlog
5.2.2 监控指标说明
| 指标名称 | 正常范围 | 告警阈值 | 说明 |
|---|---|---|---|
| 502 错误率 | 接近 0 | 1 分钟高于 1% | 多与 upstream 拒绝连接、重置连接有关 |
| 504 错误率 | 接近 0 | 1 分钟高于 0.5% | 多与 upstream 处理超时有关 |
| upstream_response_time P99 | 小于接口 SLA | 超出基线 2 倍 | 先看 upstream,再看入口超时参数 |
| 活跃连接数 | 随业务波动 | 接近设计容量 80% | 结合 worker_connections 和 FD 使用率看 |
| SYN-RECV 数 | 低位波动 | 持续升高 | 可能是 backlog 不足或攻击流量 |
| 打开文件数使用率 | 低于 70% | 高于 85% | FD 打满会引发连接失败和 502 |
5.2.3 监控告警配置
# 文件路径:prometheus/rules/nginx_5xx.yml
groups:
- name: nginx-5xx
rules:
- alert: Nginx502RateHigh
expr: |
sum(rate(nginx_http_requests_total{status="502"}[1m])) by (instance)
/
sum(rate(nginx_http_requests_total[1m])) by (instance) > 0.01
for: 2m
labels:
severity: critical
annotations:
summary: "Nginx 502 错误率过高"
description: "{{ $labels.instance }} 近 2 分钟 502 比例超过 1%"
- alert: Nginx504RateHigh
expr: |
sum(rate(nginx_http_requests_total{status="504"}[1m])) by (instance)
/
sum(rate(nginx_http_requests_total[1m])) by (instance) > 0.005
for: 2m
labels:
severity: critical
annotations:
summary: "Nginx 504 错误率过高"
description: "{{ $labels.instance }} 近 2 分钟 504 比例超过 0.5%"
- alert: NginxUpstreamP99High
expr: histogram_quantile(0.99, sum(rate(nginx_upstream_response_time_bucket[5m])) by (le, instance)) > 3
for: 5m
labels:
severity: warning
annotations:
summary: "Nginx upstream P99 响应偏高"
description: "{{ $labels.instance }} upstream P99 超过 3 秒"
5.3 备份与恢复
5.3.1 备份策略
Nginx 配置修改前先备份目录,不要只备份单个文件。线上故障时,很多人会连带改 upstream、日志、限流和缓存参数,单文件备份不够。
#!/usr/bin/env bash
# 文件名:/usr/local/bin/backup_nginx_config.sh
set -euo pipefail
TARGET="/var/backups/nginx-config-$(date +%F_%H%M%S).tar.gz"
tar czf "${TARGET}" /etc/nginx
echo "backup saved to ${TARGET}"
5.3.2 恢复流程
停止继续变更:暂停自动发布、暂停额外配置调整
恢复上一版配置:还原备份目录或从 Git/配置中心回滚
验证完整性:执行 nginx -t,确认语法、证书、include 路径都正常
热加载服务:nginx -s reload 后立即验证 200、502、504 指标
六、总结
6.1 技术要点回顾
502 和 504 不是一回事:502 更偏连接失败、无效响应、进程异常;504 更偏 upstream 处理超时
先分链路再排障:客户端、Nginx、upstream、内核网络四层拆开看,定位速度快很多
错误日志是核心证据:connect() failed、upstream timed out、reset by peer 这几个关键词很关键
超时参数不能乱拉大:很多时候真正该修的是 upstream、数据库或线程池,不是 Nginx 超时值
连接超时要看队列和内核:worker_connections、FD、somaxconn、tcp_max_syn_backlog 都会影响表现
日志字段和监控维度要打全:没有 upstream_response_time、upstream_status,排 5xx 会很被动
6.2 进阶学习方向
深入理解 Nginx 事件模型和连接生命周期
学习资源:Nginx 官方文档、源码中的 event/HTTP 模块
实践建议:结合 stub_status 和压测工具观察连接状态变化
掌握 upstream 类型差异
学习资源:HTTP proxy、FastCGI、uWSGI、gRPC 官方模块文档
实践建议:分场景调试 proxy_*、fastcgi_*、grpc_* 参数
建立入口层故障联动机制
学习资源:Prometheus、Alertmanager、日志平台、自动摘流工具
实践建议:把 502/504 告警和 upstream 健康检查、数据库慢查询联动到一起
6.3 参考资料
Nginx 官方文档 - Nginx 核心模块与参数说明
Nginx reverse proxy guide - 反向代理与 upstream 配置建议
Linux TCP tuning guide - TCP 队列和内核参数说明
OpenResty 文档 - OpenResty/Nginx 生产实践资料
附录
A. 命令速查表
nginx -t # 检查配置语法
nginx -s reload # 热加载配置
ss -s # 查看连接概况
ss -lntp | grep ':80|:443' # 查看监听状态
grep "connect() failed" /var/log/nginx/error.log # 查 upstream 拒绝连接
grep "upstream timed out" /var/log/nginx/error.log # 查 upstream 超时
curl -I -m 3 http://127.0.0.1/ # 本机验证入口层
curl -sS -o /dev/null -w '%{http_code} %{time_total}
' http://:/health # 直连 upstream
tcpdump -i any -nn host and port # 抓 upstream 通信
B. 配置参数详解
proxy_connect_timeout
作用:Nginx 与 upstream 建立连接的超时
建议:通常 1-3 秒足够,过大只会拖慢失败暴露时间
proxy_read_timeout
作用:Nginx 等待 upstream 返回响应的时间
建议:按接口类型设置,不同接口单独配置
keepalive
作用:upstream 长连接池大小
建议:按 QPS 和 upstream 并发能力估算,不要盲目拉满
worker_connections
作用:单 worker 可处理的最大连接数
建议:结合 worker_processes、FD 限制和长连接比例综合评估
backlog
作用:监听套接字的已完成连接队列长度
建议:高并发入口层保持较高值,并结合 somaxconn 一起调
C. 术语表
| 术语 | 英文 | 解释 |
|---|---|---|
| 上游服务 | upstream | Nginx 代理转发到的后端服务 |
| 连接拒绝 | connection refused | 目标端口未监听或被拒绝建立连接 |
| 连接重置 | connection reset by peer | 对端主动断开已建立连接 |
| 监听队列 | backlog | 等待应用层 accept 的已完成连接队列 |
| 长连接复用 | keepalive | 复用已建立连接,减少重复建连开销 |
D. 内核参数联动建议
Nginx 连接超时类问题,很多最后都要落到内核参数上。入口层参数和 Linux TCP 参数最好配套看,不然前端调大了,后端队列还是不够,症状不会消失。
# 文件路径:/etc/sysctl.d/99-nginx-net.conf net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 262144 net.core.netdev_max_backlog = 250000 net.ipv4.ip_local_port_range = 10240 65000 net.ipv4.tcp_fin_timeout = 15 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_syncookies = 1 fs.file-max = 2097152
应用方法:
sudo sysctl --system sysctl net.core.somaxconn sysctl net.ipv4.tcp_max_syn_backlog
这些参数的使用边界要记清楚:
somaxconn 要和 listen backlog 一起看,只改一边没有意义
ip_local_port_range 太小会导致本机发起的上游连接端口耗尽
tcp_fin_timeout 和 tcp_tw_reuse 适合连接量大的反向代理层,但上线前要在测试环境验证
fs.file-max 和进程级 nofile 要一起调,不然系统级够了,worker 级还是会撞上限
全部0条评论
快来发表一下你的评论吧 !