使用 curl 分析网络耗时
在排查网络问题时,经常需要知道一个 HTTP 请求到底慢在哪里:是 DNS 解析慢?TCP 连接慢?TLS 握手慢?还是服务端响应慢?curl 的 -w(write-out)参数可以输出请求各阶段的耗时,帮助快速定位瓶颈。
命令
curl -o /dev/null -s -w "\nDNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://app.rightcapital.com/
参数说明:
-o /dev/null:丢弃 response body,只关注耗时-s:静默模式,不显示进度条-w "...":自定义输出格式,使用内置的时间变量
请求生命周期
一个 HTTPS 请求的完整生命周期如下,每个时间变量都是从请求开始(T=0)到该阶段完成的累计时间,不是单个阶段的耗时:
|-- DNS --|-- TCP --|-- TLS --|-- Server Processing --|-- Content Transfer --|
0 time_namelookup
time_connect
time_appconnect
time_starttransfer
time_total
各阶段含义
time_namelookup — DNS 解析
从请求开始到 DNS 解析完成的时间。将域名(如 app.rightcapital.com)解析为 IP 地址。
单阶段耗时 = time_namelookup
time_connect — TCP 连接
从请求开始到 TCP 三次握手完成的时间。
单阶段耗时 = time_connect - time_namelookup
time_appconnect — TLS 握手
从请求开始到 TLS/SSL 握手完成的时间。仅在 HTTPS 请求中有值,HTTP 请求该值为 0。
单阶段耗时 = time_appconnect - time_connect
time_starttransfer — TTFB (Time To First Byte)
从请求开始到收到第一个字节的时间。这个阶段包含了发送请求和服务端处理的时间。
单阶段耗时 = time_starttransfer - time_appconnect
time_total — 总耗时
从请求开始到整个请求完成(response body 全部接收)的时间。
Content Transfer 耗时 = time_total - time_starttransfer
示例输出与分析
正常情况
DNS: 0.028s
TCP: 0.045s
TLS: 0.098s
TTFB: 0.150s
Total: 0.200s
各阶段耗时:
| 阶段 | 计算 | 耗时 | 说明 |
|---|---|---|---|
| DNS | 0.028 | 28ms | 正常 |
| TCP | 0.045 - 0.028 | 17ms | 正常 |
| TLS | 0.098 - 0.045 | 53ms | 正常 |
| Server Processing | 0.150 - 0.098 | 52ms | 正常 |
| Content Transfer | 0.200 - 0.150 | 50ms | 正常 |
DNS 慢
DNS: 2.100s
TCP: 2.130s
TLS: 2.190s
TTFB: 2.250s
Total: 2.300s
DNS 耗时 2.1s,明显异常。可能的原因:
- DNS 服务器响应慢或不可达
- 域名解析链路过长(多级 CNAME)
- 本地 DNS 缓存失效
排查方向:
# 检查 DNS 解析过程
dig app.rightcapital.com
# 对比不同 DNS 服务器的解析速度
dig @8.8.8.8 app.rightcapital.com
dig @1.1.1.1 app.rightcapital.com
# 查看完整解析链路
dig +trace app.rightcapital.com
TCP 连接慢
DNS: 0.025s
TCP: 1.500s
TLS: 1.560s
TTFB: 1.620s
Total: 1.680s
TCP 阶段耗时 1.475s(1.500 - 0.025),可能的原因:
- 服务器距离远,网络延迟高
- 网络丢包导致 TCP 重传
- 服务器端口连接队列满(backlog)
排查方向:
# 检查网络延迟
ping app.rightcapital.com
# 检查路由路径
traceroute app.rightcapital.com
# 检查特定端口的连通性
nc -zv app.rightcapital.com 443
TLS 握手慢
DNS: 0.025s
TCP: 0.045s
TLS: 1.200s
TTFB: 1.260s
Total: 1.310s
TLS 阶段耗时 1.155s(1.200 - 0.045),可能的原因:
- 证书链过长,验证耗时
- OCSP 在线验证慢(需要请求 CA 验证证书是否被吊销)
- TLS 版本协商问题
排查方向:
# 查看 TLS 握手详情
openssl s_client -connect app.rightcapital.com:443 -servername app.rightcapital.com
# 查看证书链
openssl s_client -connect app.rightcapital.com:443 -showcerts
# 指定 TLS 版本测试
curl -o /dev/null -s -w "TLS: %{time_appconnect}s\n" --tlsv1.2 https://app.rightcapital.com/
curl -o /dev/null -s -w "TLS: %{time_appconnect}s\n" --tlsv1.3 https://app.rightcapital.com/
TTFB 慢(服务端处理慢)
DNS: 0.025s
TCP: 0.045s
TLS: 0.100s
TTFB: 3.500s
Total: 3.550s
Server Processing 耗时 3.4s(3.500 - 0.100),问题出在服务端,可能的原因:
- 服务端业务逻辑慢(数据库查询、外部 API 调用)
- 服务端负载高
- 请求被排队等待处理
这种情况需要从服务端排查,网络层面没有问题。
Content Transfer 慢
DNS: 0.025s
TCP: 0.045s
TLS: 0.100s
TTFB: 0.150s
Total: 5.200s
Content Transfer 耗时 5.05s(5.200 - 0.150),可能的原因:
- Response body 过大
- 客户端和服务端之间的带宽不足
- 服务端采用 chunked 传输,边生成边发送
排查方向:
# 查看 response 大小
curl -sI https://app.rightcapital.com/ | grep -i content-length
# 加上 response size 信息
curl -o /dev/null -s -w "Size: %{size_download} bytes\nSpeed: %{speed_download} bytes/s\nTotal: %{time_total}s\n" https://app.rightcapital.com/