关键是要引入$upstream_connect_time并配合日志分析,因其仅反映TCP/TLS建连耗时,对网络抖动、连接池竞争等底层毛刺高度敏感,而$upstream_response_time含后端处理时间易掩盖真实问题。

要在 Nginx 网关层精准定位回源链路中的瞬时延迟(即“毛刺”),关键不是只看 $upstream_response_time,而是必须引入 $upstream_connect_time,并配合合理的日志格式与分析手段。
为什么 $upstream_connect_time 比 $upstream_response_time 更适合抓毛刺
$upstream_connect_time 记录的是 Nginx 与上游服务器建立 TCP 连接所耗时间(含 DNS 解析、TCP 握手、TLS 握手),它独立于后端业务逻辑,对网络抖动、连接池竞争、证书协商异常等底层问题高度敏感。而 $upstream_response_time 是整体耗时(connect + send + wait + receive),一旦后端慢了,就会掩盖连接阶段的真实毛刺。
例如:某次请求 $upstream_connect_time=320ms,但 $upstream_response_time=340ms,说明连接本身已占 94% 耗时——这极可能是 TLS 握手卡顿或上游连接池打满所致,而非后端处理慢。
在 log_format 中正确启用 $upstream_connect_time
该变量默认不可用,需确保使用的是 Nginx 1.9.1+(OpenResty ≥ 1.9.3.2),且 upstream 块中启用了 keepalive 或至少未禁用连接复用。
- 在
http块中定义日志格式,显式包含该变量:
log_format upstream_detail '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$upstream_addr $upstream_status '
'$upstream_connect_time $upstream_header_time $upstream_response_time '
'$request_time $msec';- 注意:
$upstream_connect_time在连接失败时为 “-”,成功时为毫秒级浮点数(如0.007);若始终为 “-”,检查是否用了proxy_next_upstream off或上游配置缺失 - 建议同时记录
$upstream_header_time(后端返回首字节时间),便于拆解 connect → send → wait → receive 各阶段耗时
用日志快速识别连接毛刺模式
将 access 日志导入 ELK / Loki / 或简单用 awk + sort 分析,重点关注连接时间异常分布:
- 统计 P95/P99 的
$upstream_connect_time:若 P99 > 100ms,而均值 - 筛选单次 connect > 200ms 的请求,检查是否集中出现在特定 upstream server IP(指向某台机器网络或负载异常)
- 对比同一 upstream_addr 下,
$upstream_connect_time高但$upstream_header_time低的请求——大概率是握手/建连问题,非后端响应慢 - 观察毛刺是否与 TLS 重协商、客户端 IP 段、或特定 URI(如带长 query 的健康检查路径)强相关
结合 upstream 配置做针对性优化
发现毛刺后,不能只改日志,要联动调优:
- 若毛刺集中在首次连接:增大
proxy_ssl_protocols兼容性、开启proxy_ssl_server_name on、预热 SSL session cache - 若复用连接也出现毛刺:检查
keepalive数量是否过小(如keepalive 32不足以支撑并发),或上游主动断连(调整keepalive_timeout) - 若 DNS 引发波动:改用
resolver+valid缓存,避免每次 upstream 解析都走系统阻塞查询 - 临时验证:对可疑 upstream 添加
proxy_connect_timeout 3s并捕获超时日志,确认是否因连接等待过久导致堆积











