测TTFB应聚焦服务端响应能力,用net/http设置超时、禁用重定向、关闭响应体,并调优Transport参数;Go测值偏高时先用curl -w交叉验证,避免误判瓶颈。

用 net/http 模拟真实请求测首字节时间(TTFB)
页面加载时间基准测试,核心是分离关注点:TTFB 反映后端响应能力,而完整加载时间依赖前端资源。Golang 本身不渲染页面,所以测 TTFB 是最直接、最可控的起点。
关键不是“测完页面”,而是“确认服务端瓶颈是否在 Go 这层”。http.DefaultClient 默认复用连接,但若未显式设置超时或禁用重定向,可能掩盖真实延迟。
- 务必设置
Timeout(如10 * time.Second),否则 DNS 失败或卡住会阻塞数分钟 - 禁用重定向:
CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse },避免跳转干扰 TTFB 判定 - 用
time.Now()在client.Do()前后打点,取resp.Header.Get("Date")无意义——它由服务端写入,不代表接收时机
示例片段:
start := time.Now()
resp, err := client.Do(req)
duration := time.Since(start)
if err == nil {
_ = resp.Body.Close() // 必须关,否则连接不复用
}
并发压测时 http.Transport 参数必须调优
默认 Transport 在高并发下会迅速成为瓶颈:空闲连接数少、DNS 缓存缺失、TLS 握手复用不足。不改配置,100 并发就可能测出 200ms+ 的假性延迟。
立即学习“go语言免费学习笔记(深入)”;
-
MaxIdleConns和MaxIdleConnsPerHost至少设为 200+,否则连接频繁新建销毁 -
IdleConnTimeout设为 30s,避免长连接被服务端主动断开后客户端还傻等 - 若测 HTTPS,加
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}(仅测试环境),跳过证书验证省掉 50–100ms - DNS 缓存靠
transport.DialContext+net.Resolver自定义,否则每次请求都走系统解析
区分服务端耗时与网络抖动:用 curl -w 交叉验证
Golang 测出的 TTFB 偏高?别急着优化代码。先用 curl -w "@format.txt" 对同一 URL 跑几次,比对 time_starttransfer(即 TTFB)是否一致。格式文件内容:
time_namelookup: %{time_namelookup}\n
time_connect: %{time_connect}\n
time_starttransfer: %{time_starttransfer}\n
time_total: %{time_total}\n
如果 curl 的 time_starttransfer 稳定在 12ms,而 Go 程序测出来是 80ms,大概率是 Go 客户端配置问题,不是服务端慢。
- Go 测的值 ≈ curl 的
time_starttransfer+ 少量调度开销(通常 - 若差距 > 10ms,检查是否启用了 HTTP/2(服务端支持但客户端未配
Transport的 TLS 配置) - Windows 上注意 Go 默认用 WinHTTP,行为和 curl 不同;Linux/macOS 下更接近
不要用 time.Sleep 模拟用户等待,用真实浏览器驱动补全链路
后端 TTFB 合格 ≠ 页面可用。Golang 无法测 DOM 解析、JS 执行、资源并行下载等环节。硬写个循环等几秒再发下个请求,只会得到虚假的“平均加载时间”。
真要覆盖完整链路,得交给浏览器:
- 用
chromedp启动无头 Chrome,监听Network.responseReceived和Page.loadEventFired - 关键指标取
responseReceivedTime - requestWillBeSentTime(单资源 TTFB)、loadEventFired时间戳(DOMContentLoaded) - 注意:chromedp 默认不捕获 WebSocket 或 fetch 请求的完整生命周期,需手动启用
Network.enable和Fetch.enable
单纯用 Go 测 HTTP 层,就只信它能测的部分;越界去猜前端表现,结果必然漂移。











