通过对比 $request_time 与 $upstream_response_time 差值、状态码、upstream 状态、URI 和 upstream_addr 聚类及 P95/P99 基线分析,可精准定位 Nginx 层、网络链路或后端服务的性能瓶颈。

直接看 Nginx access.log 里的 $request_time 和 $upstream_response_time,再结合状态码、上游地址、请求路径等字段交叉比对,是定位访问瓶颈最高效的方式。单看某一个指标容易误判,必须多维联动才能看清问题在哪一层、哪一类请求、哪一环卡住。
看时间差锁定瓶颈归属层
两个时间字段的差值是第一道分水岭:
- 若 $request_time − $upstream_response_time > 200ms:延迟主要在 Nginx 层或网络链路。常见原因包括 SSL 握手慢、大 body 解析耗时、gzip 压缩、proxy_buffering 关闭导致流式阻塞、客户端弱网上传
- 若两者数值接近且同时偏高(如都 ≥1.2s):问题基本在后端服务内部。需排查数据库慢查、线程池打满、GC 暂停、远程调用超时、锁竞争等
- 若 $upstream_response_time = “-” 或极小(如 0.001),但状态码是 502/504:说明 Nginx 根本没连上后端——检查端口通断、连接池耗尽、Java 进程僵死或容器未就绪
绑状态码和 upstream 状态缩小根因范围
时间只是“快慢”,状态码和 upstream 行为才告诉你是“为什么慢”:
- 502/504 + $upstream_response_time 接近 timeout 值(如 30s):后端响应超时,可能是业务逻辑卡死、DB 查询无索引、或下游依赖不可用
- 200 响应 + $request_time 高但 $upstream_response_time 很低(如 0.01s):Nginx 自身处理重,典型如大文件下载、sub_filter 替换、客户端断连重试、或日志写入阻塞
- $upstream_status 显示逗号分隔值(如 “504,200”):触发了重试机制,说明后端不稳定;若高频出现 “504,504,200”,基本可判定是后端过载而非偶发抖动
- 大量 499 状态码:客户端主动断开,常出现在页面跳转、刷新、或前端请求取消逻辑中,不是服务端问题,但可能掩盖真实慢请求
按 URI 和 upstream_addr 聚类识别热点与异常实例
把时间、状态、路径、后端地址四者关联,能快速定位是全局问题还是局部毛刺:
- 提取 耗时 Top 10 的 $request_time 对应的 $request:看是否集中在某个接口(如
/api/report/export)、某类资源(如大图/static/img/xxx.png)或特定参数组合 - 筛选 $upstream_response_time > 1s 的请求,统计 $upstream_addr 分布:如果 10.0.2.15:8080 占比超 80%,而其他实例正常,说明该后端节点异常(如 JVM GC 频繁、磁盘 I/O 阻塞)
- 对比同一路径在不同 upstream 实例上的 $upstream_response_time 差异:若差异超过 3 倍,优先检查该实例的系统负载、JVM 参数或本地缓存状态
用百分位和基线对比识别真实退化
平均值会掩盖长尾,P95/P99 才反映用户实际体感:
- 提取某核心接口(如
"GET /api/user/info HTTP/1.1")的所有 $request_time,排序后取前 5% 值作为 P95 - 对比过去 7 天同一小时段的 P95 值:若上升超 30% 且持续 2 小时以上,就是明确的性能退化信号
- 优先分析 status=200 且 $request_time > 2s 的请求,排除错误干扰,专注“成功但很慢”的场景——这类请求最值得优化


















