$request_time 无法排除网络延迟,它客观记录端到端耗时;优化关键是通过 $upstream_response_time 归因、关闭 lingering_close、限制大请求/响应及分场景日志分析,使该指标更真实反映服务层性能。

$request_time 本身无法“排除”网络延迟,它是客观记录端到端耗时的指标——包括客户端到 Nginx 的上传、Nginx 到后端的交互、以及响应返回客户端的全过程。所谓“优化以排除网络延迟”,实质是:**通过配置与日志归因,把网络侧(尤其是客户端链路)引入的不可控延迟识别出来、隔离分析,并针对性削弱其影响,从而让 $request_time 更真实反映服务层性能。**
用 $upstream_response_time 锚定服务侧耗时
这是最直接有效的归因手段。$upstream_response_time 只统计 Nginx 发起请求到收到上游响应的时间,不包含客户端网络往返。
- 若 $request_time 高但 $upstream_response_time 很低(比如 1.5s vs 0.012s),说明延迟不在后端,大概率在客户端上传慢、响应体大导致下载久、或连接异常挂起
- 若两者接近(如 1.8s vs 1.75s),说明瓶颈在上游服务,此时网络延迟已包含在 upstream 时间里,需查数据库、RPC 或上游部署环境
- 若 $upstream_response_time 为 “-” 或极小值(如 0.000),而 $request_time 很高,说明请求根本没发出去——常见于 DNS 解析失败、upstream 不可达、连接超时,这类属于基础设施层网络问题,需检查 resolver、proxy_timeout、健康检查等
关闭 lingering_close 避免假性长尾
Nginx 默认启用 lingering_close,在客户端未正常关闭连接时,会等待最多 5 秒(lingering_timeout 默认值)才彻底断开。这段时间会计入 $request_time,造成“响应快但日志显示慢”的错觉。
- 确认是否触发该机制:抓包看客户端 FIN 是否迟迟未发;或观察日志中大量 request_time 聚集在 5s 左右且 upstream_time 极短
- 解决方案:在 server 或 location 块中显式关闭:lingering_close off;,或设为 lingering_timeout 1s; 缩短等待窗口
- 注意:关闭后需确保客户端能正确处理 Connection: close,避免连接复用异常
限制大请求/大响应,减少传输依赖
客户端弱网环境下,上传大文件或下载大响应体极易拉高 $request_time,但这并非服务端处理慢,而是网络带宽或稳定性问题。
- 对上传:用 client_max_body_size 限制请求体大小,配合 client_body_timeout 快速中断卡住的上传
- 对响应:启用 gzip 压缩文本类资源;对静态文件启用 sendfile on 和 tcp_nopush on,减少内核拷贝与小包堆积
- 对流式接口:若业务允许,考虑用 chunked transfer encoding + 合理 buffer 设置(proxy_buffering on + proxy_buffers),避免 Nginx 等待完整响应再发
分离日志分析,聚焦可控环节
生产环境中,不要只盯着 $request_time 平均值。应按场景切片,过滤掉网络强相关因素后再评估:
- 排除移动端弱网请求:在日志中加入 $http_user_agent,筛选出 iOS/Android WebView 请求,单独统计其 P95 $request_time
- 排除大体积响应:用 body_bytes_sent > 100000 条件过滤,看剩余请求的 $request_time 分布是否回归合理
- 排除非关键路径:对 /health、/metrics 等探针接口,或 OPTIONS 预检请求,不纳入核心延迟监控基线











