关键在于通过$request_time与$upstream_response_time的差值定位瓶颈:二者接近说明后端慢;差值大说明nginx或网络层慢;后者为空而前者高则为静态/本地处理慢。

要在 Nginx 访问日志中识别慢查询和耗时接口,关键不是只记一个时间,而是记录多个响应时间字段,并通过它们的差值关系定位瓶颈环节。最核心的是 $request_time 和 $upstream_response_time 这两个变量——它们的数值对比,直接告诉你慢在哪一环。
配置含差值分析能力的日志格式
必须在 http 块中定义自定义日志格式,确保同时捕获总耗时与上游耗时:
-
$request_time:Nginx 接收首字节到发完响应的总时间(单位:秒,精度毫秒),代表客户端感知的完整延迟 -
$upstream_response_time:Nginx 与后端建立连接后,到收到完整响应的时间(逗号分隔,如0.002, 0.845,取第一个有效值即可) - 推荐格式(简洁实用):
log_format timing '$remote_addr - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time';
然后在 server 或 location 中启用:
access_log /var/log/nginx/timing.log timing; - 重载生效:
nginx -s reload
用差值快速归因三类典型慢因
日志写入后,无需复杂工具,仅靠字段数值关系就能初步判断问题归属:
- 后端服务慢:$request_time 与 $upstream_response_time 接近(例如 1.234 vs 1.229),且均 ≥ 0.8s → 瓶颈在应用或数据库,需查后端日志、慢 SQL
- Nginx 或网络层慢:$request_time 明显大于 $upstream_response_time(差值 ≥ 0.3s),比如 2.156 vs 0.003 → 可能是 SSL 握手、大文件上传、gzip 压缩、客户端弱网或磁盘 I/O
-
未走 upstream 的静态/本地处理慢:$upstream_response_time 为空(显示为
-),但 $request_time 很高 → 检查 rewrite 规则、sub_filter、limit_req、或静态文件读取性能
命令行提取差值并筛选慢请求
假设日志中 $request_time 是倒数第二列、$upstream_response_time 是最后一列(按实际位置调整):
- 查所有总耗时 ≥ 1s 且上游耗时 ≤ 0.1s 的“Nginx 层可疑慢请求”:
awk '$(NF-1) >= 1 && $NF - 计算每个请求的差值(Nginx 自身耗时估算),并取 Top 10:
awk '{diff = $(NF-1) - ($NF ~ /^[-0-9.]+$/ ? $NF : 0); if (diff > 0.5) print diff, $0}' /var/log/nginx/timing.log | sort -nr | head -10 - 聚焦某接口(如
/api/order/list),看其差值分布:awk '$7 ~ /^\/api\/order\/list($|\?)/ {diff = $(NF-1) - ($NF ~ /^[0-9.]+$/ ? $NF : 0); print diff}' /var/log/nginx/timing.log | sort -n | tail -5
结合状态码与路径过滤提升准确率
单看耗时容易误判,需叠加业务上下文:
- 只分析
200响应中的慢请求,排除 5xx 错误干扰:awk '$9 == 200 && $(NF-1) >= 1.0' /var/log/nginx/timing.log - 排除静态资源(.js/.css/.png 等),专注动态接口:
awk '$7 !~ /\.(js|css|png|jpg|gif|ico)$/ && $7 ~ /^\/api\// && $(NF-1) >= 0.8' /var/log/nginx/timing.log - 若某路径在高差值请求中反复出现(如占 40% 以上),基本可判定其后端存在结构性性能缺陷(如 N+1 查询、未分页全量加载)











