HTTP 接口超时排查时,最怕只知道“慢”,却不知道慢在哪一段。httpstat 的价值就在这里:它像 curl 一样发起请求,同时把 DNS 解析、TCP 连接、TLS 握手、服务端处理和内容传输等阶段的耗时拆开展示,帮助 SRE 快速判断问题更像网络侧、连接侧还是后端服务侧。
夜莺资深用户群有人推荐了这个工具,看了一下确实实用,推荐给大家。
适用场景
A 服务调用 B 服务的 HTTP 接口,发现 B 服务返回超时,但不确定原因在哪里。常见可能性包括:
- DNS 解析慢或失败。
- TCP 建连耗时高。
- TLS 握手耗时高。
- 服务端处理慢。
- 响应体传输慢。
- 代理、跨地域网络或出口链路带来额外延迟。
这时直接看应用日志可能只能看到总耗时,使用 httpstat 可以把总耗时拆成更细的阶段。
工具简介
httpstat 的使用方式和 curl 类似,也可以请求某个后端接口。不同之处在于,它会把一次 HTTP 请求拆成多个阶段,并把每个阶段的耗时展示出来:
| 阶段 | 含义 | 排查价值 |
|---|---|---|
| DNS Lookup | 域名解析耗时 | 判断 DNS 服务、域名解析链路是否异常。 |
| TCP Connection | TCP 建连耗时 | 判断网络连通性、跨地域链路或服务端端口响应问题。 |
| TLS Handshake | TLS 握手耗时 | 判断证书、加密协商、HTTPS 链路是否拖慢请求。 |
| Server Processing | 服务端处理并等待响应耗时 | 判断后端应用、数据库或下游依赖是否慢。 |
| Content Transfer | 响应体传输耗时 | 判断响应体大小、带宽或客户端读取是否异常。 |
效果如下:

这个工具是 Go 写的,作者没有提供二进制包,所以需要自己编译安装。
安装 Go 环境
自己编译就需要有 Go 环境。下面以 Mac M1 为例,先下载 Go 安装包(https://go.dev/dl/):https://go.dev/dl/go1.22.2.darwin-arm64.tar.gz。一般使用 tar.gz 文件即可,不一定要用 pkg。
cd /Users/ulric/works/tgz
wget https://go.dev/dl/go1.22.2.darwin-arm64.tar.gz
tar -zxf go1.22.2.darwin-arm64.tar.gz
操作如上,/Users/ulric/works/tgz/go 这个目录就是 go 的安装目录,然后配置环境变量:
export GOROOT=/Users/ulric/works/tgz/go
export GOPATH=/Users/ulric/works/gopath
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
GOROOT 是 go 的安装目录,GOPATH 是 go 的工作目录,PATH 是环境变量,这样配置之后,就可以使用 go 命令了。上面的几行命令可以保存在 ~/.bash_profile 或者 ~/.zshrc 里,这样每次打开终端都会自动加载。
验证 Go 环境是否正常安装:
% go version
go version go1.22.2 darwin/arm64
安装 httpstat
有了 Go 环境后,安装 httpstat 就很简单:
ulric@ulric-flashcat ~ % go install github.com/davecheney/httpstat@latest
go: downloading github.com/davecheney/httpstat v1.1.0
go: downloading golang.org/x/sys v0.0.0-20201223074533-0d417f636930
测试 httpstat
安装完成之后,先看看 httpstat 有哪些参数可用:
ulric@ulric-flashcat ~ % httpstat --help
Usage: httpstat [OPTIONS] URL
OPTIONS:
-4 resolve IPv4 addresses only
-6 resolve IPv6 addresses only
-E string
client cert file for tls config
-H value
set HTTP header; repeatable: -H 'Accept: ...' -H 'Range: ...'
-I don't read body of request
-L follow 30x redirects
-O save body as remote filename
-X string
HTTP method to use (default "GET")
-d string
the body of a POST or PUT request; from file use @filename
-k allow insecure SSL connections
-o string
output file for body
-v print version number
ENVIRONMENT:
HTTP_PROXY proxy for HTTP requests; complete URL or HOST[:PORT]
used for HTTPS requests if HTTPS_PROXY undefined
HTTPS_PROXY proxy for HTTPS requests; complete URL or HOST[:PORT]
NO_PROXY comma-separated list of hosts to exclude from proxy
很多参数和 curl 都很像。比如先用 curl 测试一个 POST 请求:
ulric@ulric-flashcat ~ % curl -X POST -H "Content-Type: application/json" -d '{"service": "tomcat"}' 'https://httpbin.org/post?name=ulric&city=beijing'
{
"args": {
"city": "beijing",
"name": "ulric"
},
"data": "{\"service\": \"tomcat\"}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Content-Length": "21",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "curl/8.4.0",
"X-Amzn-Trace-Id": "Root=1-6655a6c4-4522374c5b8d68143d638049"
},
"json": {
"service": "tomcat"
},
"origin": "123.113.255.104",
"url": "https://httpbin.org/post?name=ulric&city=beijing"
}
把 curl 换成 httpstat,请求效果如下:
ulric@ulric-flashcat ~ % httpstat -X POST -H "Content-Type: application/json" -d '{"service": "tomcat"}' 'https://httpbin.org/post?name=ulric&city=beijing'
Connected to 34.198.16.126:443
HTTP/2.0 200 OK
Server: gunicorn/19.9.0
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Content-Length: 529
Content-Type: application/json
Date: Tue, 28 May 2024 09:41:44 GMT
Body discarded
DNS Lookup TCP Connection TLS Handshake Server Processing Content Transfer
[ 11ms | 217ms | 446ms | 570ms | 0ms ]
| | | | |
namelookup:11ms | | | |
connect:229ms | | |
pretransfer:678ms | |
starttransfer:1248ms |
total:1248ms
可以看到,httpstat 把请求的各个阶段耗时都展示出来了。
如何解读输出
上面的输出里,总耗时是 1248ms,其中:
namelookup:11ms:DNS 解析很快,不像是主要瓶颈。connect:229ms:TCP 连接完成时间约为 229ms。pretransfer:678ms:TLS 握手完成后进入可发送请求的状态。starttransfer:1248ms:收到首字节时已经达到 1248ms,主要时间消耗在连接完成后的等待阶段。total:1248ms:整体请求完成时间。
排查时可以先看哪个阶段明显异常:
| 现象 | 优先怀疑方向 |
|---|---|
| DNS Lookup 很高 | DNS 服务、解析链路、域名配置。 |
| TCP Connection 很高 | 网络链路、服务端端口、跨地域访问、代理。 |
| TLS Handshake 很高 | HTTPS 握手、证书协商、客户端与服务端加密性能。 |
| Server Processing 很高 | 后端应用、数据库、缓存、下游服务或线程池。 |
| Content Transfer 很高 | 响应体过大、带宽不足、客户端读取慢。 |
使用注意事项
httpstat 适合做单次请求的快速定位,但它不能替代长期监控。生产排障时,建议和服务端日志、APM Trace、指标大盘、网关日志一起看。
如果一个接口偶发超时,可以多执行几次,观察慢的阶段是否稳定。如果每次慢的位置不同,问题可能不是单点瓶颈,而是网络抖动、代理链路、下游依赖或服务端资源竞争。
FAQ
Q1:已经有 curl 了,还需要 httpstat 吗?
需要看场景。curl 很适合验证请求是否能通,httpstat 更适合把一次请求的阶段耗时拆开看。
Q2:httpstat 能判断根因吗? 它不能直接给出根因,但能缩小排查范围。例如 Server Processing 高,说明应该优先看服务端和下游依赖;DNS Lookup 高,则先看解析链路。
Q3:它适合放到监控系统里长期跑吗? 这篇文章主要介绍临时排障用法。长期探测建议使用专门的黑盒探测、合成监控或拨测方案。
