nginx 通过 $upstream_response_time 变量记录后端响应时间(秒级,毫秒精度,多值逗号分隔),配合 log_format 写入 access log;需结合 $upstream_addr 和 $upstream_status 分析重试行为,并可用 map 指令按阈值分级标记。

在 Nginx 中,要获取后端服务(如 upstream 代理的服务器)的具体响应时间,核心是使用内置变量 $upstream_response_time,它记录了 Nginx 与后端建立连接、发送请求、接收响应所花费的总时间(单位:秒,精度为毫秒,以逗号分隔多个请求的时间)。配合日志模块,即可将该时间写入 access log 进行记录和分析。
启用并配置 upstream 响应时间日志
确保你的 Nginx 配置中启用了 log_format 并包含 $upstream_response_time。例如:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$upstream_response_time $request_time';
access_log /var/log/nginx/access.log main;
其中:
-
$upstream_response_time:后端实际处理时间(如 FastAPI、Tomcat 等返回第一个字节的时间),多个 upstream 节点会以逗号分隔(如0.023, 0.045); -
$request_time:整个请求从读取首行到日志写入的总耗时(包括网络延迟、Nginx 处理、后端响应等),通常 ≥$upstream_response_time。
区分单次与多次 upstream 请求
如果配置了重试(如 proxy_next_upstream error timeout),一次客户端请求可能触发多次后端调用,此时 $upstream_response_time 会记录所有尝试的时间(逗号分隔)。可通过以下方式辅助判断:
- 结合
$upstream_addr查看具体连接的后端地址; - 用
$upstream_status匹配各次响应状态码(也以逗号分隔),定位哪次调用失败或超时; - 若只希望记录最终成功那次的响应时间,需在应用层或日志分析阶段过滤(Nginx 本身不提供“仅最后一次”变量)。
验证与调试技巧
快速确认变量是否生效:
- 临时添加一个 debug 日志格式,只输出关键时间变量;
- 用
curl -I http://your-domain/触发请求,检查日志中是否出现非短横线(-)的数值(-表示未连接后端,如静态资源直出); - 对比
$upstream_response_time和$request_time:若后者明显更大,说明 Nginx 自身处理或网络传输有开销;若两者接近,瓶颈大概率在后端。
进阶:按响应时间做条件日志或监控
可结合 map 指令对响应时间分级,便于后续统计:
map $upstream_response_time $rt_level {
~^[0-9]*\.[0-5][0-9]{2}$ "fast";
~^[0-9]*\.[6-9][0-9]{2},?$ "slow";
default "unknown";
}
log_format timed '$remote_addr [$time_local] $request '
'$upstream_response_time $rt_level';
这样日志中就能标记 “fast” 或 “slow”,方便用脚本或 ELK 快速聚合慢请求比例。











