要通过nginx日志做性能分析,必须自定义log_format包含$request_time、$upstream_response_time等关键耗时字段,再用awk按接口筛选、交叉比对多字段归因慢因,并用分位数(如p95)和区间统计替代平均值分析长尾延迟。

要通过 Nginx 日志做性能分析、定位慢请求和耗时接口,核心是让日志“说真话”——必须记录关键时间字段,并用结构化方式提取、比对、归因。不光看总耗时大不大,更要拆开看时间花在哪。
确保日志格式包含必要耗时变量
默认日志(如 combined)不含任何时间字段,无法分析性能。需在 http 块中定义自定义格式,至少包含:
- $request_time:从收到第一个字节到发完最后一个字节的总耗时(单位:秒,精度毫秒)
- $upstream_response_time:Nginx 与后端(如 Tomcat、PHP-FPM)交互的真实响应耗时;若走 proxy_pass,该值有效;若为静态资源或 rewrite 处理,通常为空或 “-”
- 强烈建议补充:$upstream_connect_time(建连耗时)、$upstream_addr(实际通信后端地址),便于定位具体实例
示例配置:
log_format perf '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time $upstream_connect_time $upstream_addr';
access_log /var/log/nginx/perf.log perf;
配置后执行 nginx -s reload 生效。
按接口路径精准筛选耗时数据
想分析某个具体接口(如 /api/order/list),不能只扫全量日志。用 awk 按请求路径匹配并提取耗时:
- 只输出该接口所有请求的耗时值(便于后续统计):
awk '$7 ~ /^\/api\/order\/list($|\?)/ {print $NF}' /var/log/nginx/perf.log - 同时输出路径和耗时(方便人工核对):
awk '$7 ~ /^\/api\/order\/list($|\?)/ {print $7, $NF}' /var/log/nginx/perf.log - 注意:$7 是默认字段位置,若你自定义了 log_format,先用 head -1 perf.log | awk '{print NF; print $0}' 确认 $request_uri 和 $request_time 分别在第几列
用命令行快速归因三类典型慢因
单看一个数字没意义,要结合多个字段交叉判断瓶颈归属:
- 后端服务慢:$upstream_response_time 高(如 >0.8s),且与 $request_time 接近(差值
- 网络或连接问题:$upstream_connect_time 显著偏高(如 >500ms),但 $upstream_response_time 正常 → 检查 DNS、后端连接池、网络丢包
- Nginx 或客户端侧慢:$request_time 高(如 2.3s),但 $upstream_response_time 极低(如 0.002s)或为空 → 考虑 SSL 握手、大文件上传、gzip 压缩、客户端弱网、或 proxy_buffering off 导致阻塞
常用排查命令:
- 查所有 $request_time ≥ 1s 的请求:awk '$NF > 1' /var/log/nginx/perf.log
- 看哪个后端最常超时:awk '$8 > 1 {print $9}' /var/log/nginx/perf.log | sort | uniq -c | sort -nr(假设 $8 是 upstream_response_time,$9 是 upstream_addr)
- 对比总时间和后端时间差值:awk '$NF - $(NF-1) > 0.3 {print $0}' /var/log/nginx/perf.log(差值超 300ms 的请求)
统计分位数而非平均值,关注长尾延迟
平均值容易被少量慢请求拉高或掩盖问题。应重点看 P95、P99 耗时:
- 计算 P95(95% 请求耗时低于该值):
awk '$NF ~ /^[0-9.]+$/ {a[NR]=$NF} END {n=int(NR*0.95); asort(a); print a[n]}' /var/log/nginx/perf.log - 按毫秒区间统计分布(如 0–99ms、100–499ms、≥500ms):
awk '$NF ~ /^[0-9.]+$/ {t=$NF*1000; if(t - 找出单次最慢的 10 个请求:
awk '$NF ~ /^[0-9.]+$/ {print $NF, $0}' /var/log/nginx/perf.log | sort -nr | head -10











