$upstream_connect_time 显示“0.000”或为空,是因为该变量仅在TCP连接成功建立后赋值;若DNS解析失败、连接被拒绝、超时或未执行connect阶段,变量保持空或0,且Nginx不主动报错提示。

为什么 $upstream_connect_time 显示为 “0.000” 或空?
这个变量只在成功建立 TCP 连接后才被赋值;如果连接超时、被拒绝、或根本没走到 connect 阶段(比如 DNS 解析失败、上游 server 不可达),它就保持为空或 0。Nginx 不会在 error_log 里主动提示“connect 失败所以 $upstream_connect_time 无效”,容易误判为“建连很快”。
- 检查
error_log级别是否为info或更高,确认有无connect() failed、no live upstreams类日志 - 用
tcpdump或strace -e trace=connect,sendto,recvfrom -p $(pidof nginx)验证 Nginx worker 是否真发出了 connect 系统调用 - 确保你在
log_format中引用的是$upstream_connect_time,而不是拼错成$upstream_conn_time(后者不存在)
如何让 $upstream_connect_time 稳定输出毫秒级精度?
Nginx 默认对 $upstream_connect_time 做了三位小数截断(即 0.001s 精度),但底层实际记录的是微秒级时间戳。要真正看到亚毫秒差异(比如 0.0002s → 0.2ms),必须配合 log_format 的格式化控制。
- 在
http块中定义日志格式:log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_addr $upstream_connect_time $upstream_header_time $upstream_response_time'; - 关键点:不要用
log_format里的$upstream_connect_time直接参与计算,它本质是字符串;如需数值比较,应在日志采集侧(如 Filebeat + Logstash)做float($upstream_connect_time)转换 - 注意:该变量仅在
proxy_pass、fastcgi_pass等 upstream 指令生效的 location 中可用,return或rewrite阶段不可用
对比 $upstream_connect_time 和 $upstream_header_time 才能定位真实瓶颈
$upstream_connect_time 只反映从发起 connect() 到收到 SYN-ACK 的耗时;而 $upstream_header_time 是从 connect 完成到收到后端第一个响应字节(即 header)的时间,中间包含 TLS 握手、请求发送、后端处理等全部环节。两者差值过大,说明问题不在建连本身。
- 典型健康模式:
$upstream_connect_time ≈ 0.001–0.005,$upstream_header_time − $upstream_connect_time (即 TLS+处理 <li>若 <code>$upstream_connect_time正常(如 0.002),但$upstream_header_time高达 2.341,则瓶颈在后端处理或 TLS 握手(尤其启用了 client_certificate 验证时) - 若两者都高且接近(如均为 1.823),大概率是网络 RTT 高或后端 listen backlog 溢出,导致 accept() 延迟——这时要查后端
ss -lnt的Recv-Q是否持续非零
在 upstream block 中启用 keepalive 后,$upstream_connect_time 还有意义吗?
有意义,但语义变了:它只对**新建连接**生效。启用 keepalive 32 后,绝大多数请求复用已有连接,此时 $upstream_connect_time 会稳定为 0.000(Nginx 文档明确说明:“not set for keepalive connections”)。不能因此认为“建连没问题”,反而说明你压根没观察到建连阶段。
- 临时关闭 keepalive:
keepalive 0或注释掉该行,再压测,才能捕获真实建连延迟 - 更稳妥的做法:在日志中同时记录
$upstream_addr和$upstream_connect_time,筛选出带端口号且$upstream_connect_time != "0.000"的日志行,这些就是真实的新建连接样本 - 注意:关闭 keepalive 会显著增加后端 TIME_WAIT 和 CPU 开销,仅限诊断使用,切勿长期开启
真正难的是区分“建连慢”和“建连被阻塞”——前者是网络或后端 listen 队列问题,后者可能是 Nginx resolver 超时、上游 server 名称解析卡住,而 $upstream_connect_time 对这两种情况都沉默。这时候得去翻 resolver_timeout 设置和 dig +trace 输出。


















