

新闻资讯
技术学院应使用 httptest.NewServer 搭配 testing.Benchmark 测接口调用,避免直接发真实 HTTP 请求;只压测客户端逻辑(如序列化、重试策略),必要时用 hey 或 vegeta 做端到端测试。
testing.Benchmark 测接口调用,但别直接测 HTTP 请求Go 的 Benchmark 函数本身不处理网络延迟抖动,直接在 Benchmark 里发真实 HTTP 请求会导致结果不可靠——每次运行受网络、服务端负载、DNS 解析等干扰,benchstat 也难比出有效差异。
hey -n 1000 -c 50 http://localhost:8080/api 或 vegeta attack -targets=targets.txt -rate=100 -duration=30s
httptest.NewServer,确保每次 Benchmark 走同一内存服务,排除网络变量httptest.NewServer 搭配 Benchmark 的标准写法这是最可控的接口调用性能测试路径:用 httptest 启一个固定响应的服务,再让 client 轮询它。所有耗时都反映 client 侧行为(编码、transport 复用、错误处理等)。
func BenchmarkHTTPClientCall(b *testing.B) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte(`{"id":1,"name":"test"}`))
}))
defer srv.Close()
client := &http.Client{
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
req, _ := http.NewRequest("GET", srv.URL+"/api", nil)
resp, err := client.Do(req)
if err != nil {
b.Fatal(err)
}
io.ReadAll(resp.Body)
resp.Body.Close()
}}
b.ResetTimer(),把 httptest.NewServer 启动和 client 初始化时间剔除io.ReadAll(resp.Body) 必须执行,否则连接可能被复用失败或触发 idle timeouthttp.Client 或 http.Request —— 这会掩盖真实瓶颈json.Marshal/json.Unmarshal
很多“接口慢”实际卡在 payload 处理。用 Benchmark 单独压测编解码,能快速定位是否该换 easyjson 或 msgpack。
var payload = struct {
ID int `json:"id"`
Name string `json:"name"`
}{ID: 123, Name: "benchmark-test"}
func BenchmarkJSONMarshal(b *testing.B) {
for i := 0; i < b.N; i++ {
, = json.Marshal(payload)
}
}
func BenchmarkJSONUnmarshal(b *testing.B) {
data, _ := json.Marshal(payload)
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v struct{ ID int; Name string }
json.Unmarshal(data, &v)
}
}
json.Marshal 一次生成 data,避免在循环里重复编码干扰解码测试Unmarshal 耗时 > 100ns/op,且字段多、嵌套深,值得引入 easyjson 生成静态方法默认 http.DefaultClient 的 Transport 是共享的,Benchmark 多次运行会复用连接池,但首次请求仍要建连。如果你测的是“冷启动首请求”,得显式关掉 keep-alive:
req.Header.Set("Connection", "close") 强制每次新建 TCP 连接Transport.MaxIdleConns = 0 禁用空闲连接复用Timeout 设置过短会导致大量 context
deadline exceeded 错误,压测时建议设为 30 * time.Second 以上真正上线前,transport 参数必须和生产环境一致,否则 benchmark 结论毫无意义。