$upstream_response_time 记录 Nginx 发送完请求到接收响应首字节的时间,不含 DNS、TCP/SSL 建立及响应体生成耗时;需配合 keepalive、禁用隐式重试、日志清洗与 trace ID 关联,才能真实反映后端业务处理耗时。

要在 Nginx 日志中准确记录上游服务的真实业务响应时间,关键不是简单添加变量,而是理解 $upstream_response_time 的行为边界,并配合日志格式、上游配置和业务协同,才能让它真正反映“后端处理耗时”。
明确 $upstream_response_time 的真实含义
该变量记录的是 Nginx 与 upstream server 建立连接后,从发送完整请求(request body 发送完毕)到接收到第一个字节响应(response header 开始接收)之间的时间。它不包含:DNS 解析、TCP 连接建立(若未复用)、SSL 握手、请求体传输延迟、以及后端生成响应体(如大文件流式输出)的耗时。因此它最贴近“后端应用处理逻辑 + 网络往返”的耗时,但前提是后端尽快返回 header。
启用并验证变量可用性
确保你使用的是标准 Nginx(非极简版),该变量默认编译进核心模块,无需额外加载。在 http 或 server 块中定义日志格式:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$upstream_response_time $request_time $upstream_addr';注意:
- $upstream_response_time 是一个字符串,可能含多个值(如负载均衡多台、重试),例如 "0.024, 0.105";
- 若请求未进入 upstream(如静态文件、rewrite 拦截、4xx 错误),该值为 -;
- 建议同时记录 $request_time(客户端全程耗时)和 $upstream_addr(实际通信地址),便于比对分析。
优化 upstream 配置以提升指标真实性
让 $upstream_response_time 更可靠,需减少干扰因素:
-
启用 keepalive:避免每次请求重建 TCP/SSL 开销,使该变量更聚焦于后端处理。在 upstream 块中添加:
keepalive 32;,并在 location 中设置:proxy_http_version 1.1; proxy_set_header Connection ''; -
禁用缓冲(谨慎):若后端业务逻辑在返回 header 后才开始生成 body(如导出大报表),可设
proxy_buffering off;,此时$upstream_response_time会延长至第一个响应字节到达——但这会增加 worker 占用,仅建议调试期临时开启 -
避免隐式重试:确认
proxy_next_upstream未对 5xx/timeout 过度重试,否则日志中会出现多个逗号分隔值,主耗时被稀释。建议显式控制重试次数:proxy_next_upstream_tries 2;
日志采集与下游分析建议
原始日志中的多值字段需清洗后才可用于监控:
- 用 Logstash / Fluentd 提取首个值(即首次 upstream 耗时):
%{NUMBER:upstream_first_time:float};或取平均/最大值,视监控目标而定 - 在 Prometheus + nginx-vts-exporter 或自定义 exporter 中,将
$upstream_response_time映射为直方图(histogram)指标,按 upstream 名分组,观察 P95/P99 分布 - 结合 trace ID(如通过
proxy_set_header X-Request-ID $request_id;)关联后端日志,验证 Nginx 记录是否与后端打点一致——这是确认“真实业务耗时”的黄金标准


















