使用 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/