Nginx常见故障排查手册

描述

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 host  and 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 级还是会撞上限

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分