线上最常见的一句反馈就是“接口慢”。但如果不把耗时拆开,这句话几乎没有排障价值。慢到底慢在 DNS、TCP 建连、TLS 握手、服务处理,还是响应体下载,必须拆出来才能继续判断。
HTTP 排障最容易犯的错误,是把总耗时当成唯一指标。真正有价值的是把总时间拆成多个阶段,然后看瓶颈究竟落在哪一步。
为什么 curl 特别适合做第一层判断
浏览器适合使用,但不适合做最小现场分析。curl 的价值在于它足够轻、足够可控,而且可以把请求过程拆成多个时间段输出出来。
一个最常用的命令如下:
1 | curl -o /dev/null -s -w 'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} starttransfer:%{time_starttransfer} total:%{time_total}\n' https://example.com |
这里几个字段非常重要。
time_namelookup表示 DNS 解析完成时间。time_connect表示 TCP 建连完成时间。time_appconnect表示 TLS 握手完成时间。time_starttransfer表示收到首字节时间,也常被理解为 TTFB。time_total表示整个请求结束时间。
只要把这些时间拆开,很多“接口慢”的问题就已经不再模糊。
一次标准的分析方式
假设某个接口总耗时 2 秒,不要急着说后端慢,先看每段耗时分布。
如果 dns 很高,那就先排 DNS。
如果 connect 很高,那就先看 TCP 建连和链路质量。
如果 tls 很高,那就重点看证书、握手和协商过程。
如果前面都很快,但 starttransfer 很高,那更像是服务端处理、缓存未命中、回源慢或者中间代理等待。
如果首字节很快,但 total 很慢,那要继续看响应体是否过大、是否有流式返回、是否存在客户端接收瓶颈。
配合详细输出一起看
时间拆解之外,再配合 -v 看过程会更完整。
1 | curl -v https://example.com |
这里你可以观察到。
- 实际连接的 IP。
- 是否复用了已有连接。
- 请求头和响应头。
- 是否经过重定向。
- TLS 握手的一些关键信息。
如果服务经过 CDN、反向代理或网关,响应头里还常常会带一些非常有价值的排障线索,比如缓存命中状态、边缘节点标识、上游处理时间等。
一条更贴近实战的排查链路
面对慢请求,我一般会先用下面这个组合。
1 | curl -v -o /dev/null -s -w 'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} starttransfer:%{time_starttransfer} total:%{time_total}\n' https://example.com/api |
如果发现 connect 和 tls 都很快,而 starttransfer 明显偏高,就说明网络建连大概率没问题,应更多怀疑服务处理、缓存命中、回源、数据库或下游依赖。
如果 dns 明显偏高,就先去对比不同 DNS 结果。
如果 connect 明显偏高,再结合 ss、tcpdump 看连接阶段是否存在重传或等待。
如果 tls 明显偏高,就需要进一步看 HTTPS 握手细节。
这就是为什么 HTTP 排障不能只盯着一个总耗时数字。因为同样是“2 秒”,背后可能是完全不同的系统问题。
常见误判
第一个常见误判,是把 TTFB 慢直接等同于应用代码慢。实际上,负载均衡等待、反向代理排队、CDN 回源、上游链路拥塞,都可能让首字节变慢。
第二个常见误判,是用浏览器手感代替数据。页面觉得慢,不代表接口真的慢;接口慢,也不代表 DNS 或 TLS 慢。没有时间拆解,就很容易把问题归因错。
第三个常见误判,是忽略重定向和连接复用。有时第一次慢是因为握手和重定向,后续请求快很多;如果不看过程,很容易误以为服务本身抖动。
一个值得自己做的小实验
你可以对同一个站点连续发几次请求,并记录每一段时间。
1 | curl -o /dev/null -s -w 'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} starttransfer:%{time_starttransfer} total:%{time_total}\n' https://example.com |
然后观察。
- 第一次和后两次相比,是否有明显差异。
- 是哪一段时间差异最大。
- 如果请求一个静态资源和一个动态接口,两者瓶颈分别在哪。
这个实验特别适合训练“先拆阶段,再下结论”的习惯。
小结
HTTP 请求耗时分析真正的关键,不是把请求发出去,而是把时间拆开。只要你能用 curl 把 DNS、建连、TLS、首字节和总耗时分开看,“接口慢”这类原本非常笼统的问题,就会开始变成结构化问题。排障最怕模糊,而时间拆解恰好就是把模糊打碎的第一步。