高并发下需预设强分隔日志格式并实时统计状态码:用$status |开头确保字段稳定,配合tail -f+awk或nginxlog-exporter+prometheus秒级监控5xx,结合stub_status和三步检查法定位nginx或后端瓶颈。

直接在高并发场景下测试状态码分布,核心不是“压测时看一眼日志”,而是提前配置好可稳定提取的状态码字段 + 实时流式统计能力。否则压测一上来日志就乱、字段错位、统计失真,根本没法定位是 Nginx 本身扛不住,还是后端崩了。
确保日志格式能抗住高并发解析
默认 combined 格式里 $status 在第 9 字段,但 $http_user_agent 含空格或引号时,awk '{print $9}' 会偏移。高并发下这种错误会被放大。
必须显式前置并用强分隔符隔离:
log_format high_conc '$status | $remote_addr [$time_local] "$request" '
'$body_bytes_sent "$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time $upstream_status';
access_log /var/log/nginx/conc.log high_conc buffer=64k flush=1s;
-
buffer=64k flush=1s:减少磁盘 IO 频次,又避免日志延迟超过 1 秒 -
$status |开头 →$status恒为第 1 字段,awk '{print $1}'安全可靠 - 显式包含
$upstream_status:区分是 Nginx 层失败(如 502 连不上),还是后端真返回了 500
压测中实时抓取与滚动统计
别等压测结束再扫日志。用 tail -f 配合轻量聚合,秒级反馈异常趋势:
- 每 5 秒输出当前 5xx 占比(基于最近 1000 行):
tail -n +1 -f /var/log/nginx/conc.log | \ awk -v win=1000 '{ c[$1]++; total++; if (NR > win) { prev = substr($0,1,3); # 简单取前3字符作伪时间戳,实际可用$2 if (prev in first) delete first[prev]; } first[NR%win] = $1; if (NR%win==0) { xx5 = 0; for (i in c) if (i ~ /^5/) xx5 += c[i]; printf "%.1f%% 5xx (%d/%d)\n", xx5*100/total, xx5, total > "/dev/stderr"; c = ""; total = 0; } }'
更推荐用 nginxlog-exporter 或 Telegraf + grok,把每行日志转成指标如 nginx_status_count{code="502", host="api"},喂给 Prometheus,再设告警规则:
- alert: HighUpstream5xxRate
expr: rate(nginx_upstream_status_count{code=~"5.."}[2m])
/ rate(nginx_upstream_status_count[2m]) > 0.03
for: 4m
结合 stub_status 验证 Nginx 自身承载力
状态码异常时,先排除是不是 Nginx worker 崩了或连接打满了:
- 访问
/status(需启用stub_status):Active connections: 1247 server accepts handled requests 23456789 23456789 34567890 Reading: 2 Writing: 124 Waiting: 1131
- 关键看
Waiting是否长期 > 90% 的worker_connections -
Reading/Writing持续高位 → 可能上游响应慢,Nginx 在等;Waiting高 → 请求堆积在队列,worker 不够或处理阻塞
压测后快速归因的三步检查法
-
筛出突增时段的 5xx 请求路径:
awk '$1 ~ /^5/ && $2 ~ /09\/Sep\/2026:14:2[5-7]/ {print $4}' conc.log | sort | uniq -c | sort -nr | head -5 -
查这些路径对应的 upstream_status:
awk '$1 ~ /^5/ && $4 ~ /\/api\/order/ {print $NF}' conc.log | grep -v "-" | sort | uniq -c # 若大量 "504" → proxy_read_timeout 不足;若大量 "502" 且 upstream_status="-" → 后端端口未监听或被防火墙拦 -
对比 error.log 同一时段错误:
grep "2026:14:2[5-7]" /var/log/nginx/error.log | grep -E "(connect|timeout|upstream)"
不复杂但容易忽略











