KernelRanch
返回文章列表

用 curl 定位接口问题:-w 的五个时间戳比 -v 更有用

2026-11-10 #curl#http#troubleshooting#cheatsheet

接口慢了,第一反应常是加日志。其实一条 curl -w 就能把时间拆开,看出慢在 DNS、连接、握手,还是服务端。

1. 一条命令看五段

curl -s -o /dev/null -w "dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total} code=%{http_code}\n" https://example.com/

真实输出(本机访问 quote.kernelranch.com/2fa,2026-11-10):

dns=0.278397 connect=0.538940 tls=0.821185 ttfb=1.116068 total=1.704376 code=200

五段的关系是包含的:connect 包含 dns,tls 包含前两者,ttfb 包含全部前置动作,total 是收完响应体的时间。要做减法看增量:

增量计算慢在这里说明什么
DNSdns解析慢,检查递归解析器、DoH、或域名本身
TCP 建连connect - dns网络或服务端 accept 慢
TLS 握手tls - connect证书链、OCSP、TLS 版本协商
服务端处理ttfb - tls应用逻辑、数据库、上游调用
传输total - ttfb响应体大或带宽不足

上面那次的增量是:DNS 0.28s、TCP 0.26s、TLS 0.28s、服务端 0.29s、传输 0.59s。四段几乎平均,说明不是单点问题,而是链路整体偏慢——这种时候换机房比调代码有用。

2. 退出码比状态码更早暴露问题

code=000 表示没有拿到 HTTP 响应,具体原因看退出码:

退出码含义典型原因
6无法解析主机域名拼错、DNS 不可用
7连接被拒端口没监听、防火墙
28超时对端不响应或太慢
35TLS 握手失败证书、协议版本、SNI

实测访问一个不存在的域名:

code=000 dns=0.000000
exit=6

DNS 耗时为 0 且退出码 6,说明请求根本没发出去。

3. 三个常用组合

# 只看状态码(脚本里最常用)
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/

# 限制总时长,避免脚本挂死
curl -s --max-time 5 -o /dev/null -w "%{http_code}\n" https://example.com/

# 指定解析结果,绕过本地 DNS 或验证新 IP
curl -s --resolve example.com:443:203.0.113.10 https://example.com/

--resolve 在切换 DNS、验证新服务器时特别有用:不用改 hosts,也不用等缓存过期。

4. 两个坑

PowerShell 里的 curl 可能不是 curl。Windows PowerShell 5.x 把 curl 别名指向 Invoke-WebRequest,于是 -w、-o 这些参数全报错。判断方法:

Get-Command curl | Select-Object Name, CommandType, Source

要真 curl 就写 curl.exe。本机实测 curl.exe -s -o NUL -w ... 正常,-o /dev/null 在 Windows 上要换成 NUL。

-w 里的变量要加百分号并转义。在 bash 里 %{time_total} 直接可用;在 Windows 的 cmd 里不需要转义,但在 PowerShell 双引号中 % 没有特殊含义,可以照写;如果放进 bash -c,记得单引号包裹。

小结

-v 告诉你请求和响应长什么样,-w 告诉你时间花在哪。排查慢接口先看 -w 的增量,再看 -v 的握手细节,最后才去翻服务端日志。

一个容易忽略的细节:total - ttfb 如果占比很高,往往不是服务端慢,而是响应体太大或客户端带宽不够。这时候优化 SQL 是白费功夫。

数据来源与检索时间

检索时间 2026-11-10。计时数据为本机实测。

来源URL对应数据
curl 手册《--write-out》https://curl.se/docs/manpage.htmltime_namelookup、time_connect、time_appconnect、time_starttransfer、time_total 的定义与包含关系;--resolve 语义
curl 退出码说明https://curl.se/docs/manpage.html#EXITCODES退出码 6/7/28/35 的含义
Microsoft Learn《about_Aliases》https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_aliasesWindows PowerShell 中 curl 别名为 Invoke-WebRequest 的行为

核验说明

  • 第 1、2 节的计时输出与退出码均为本机执行结果(curl 8.x,Windows 11)。
  • 未做:没有在丢包、高延迟链路上验证各段耗时分布;没有测试 HTTP/2 与 HTTP/3 下 time_appconnect 的差异。