用 net/http 并发请求时须自定义 http.Client:设 Timeout(如10s)、MaxIdleConns 与 MaxIdleConnsPerHost(建议≥2000)、调整 IdleConnTimeout;并发控制用 sync.WaitGroup + channel,避免默认配置导致客户端瓶颈。
用
发起并发请求,别碰
默认超时
Go 自带的
能扛住高并发,但默认配置会拖垮压测结果:
的
是 0(无限等待),而底层
的
和
默认只有 100,一压就卡在连接池排队。实际压测必须显式构造 client:
设置
控制单次请求上限,比如
调大
和
,建议至少设为 2000
关闭
或设为较大值,避免连接被过早回收
不改这些,你看到的 QPS 上不去,不是服务端瓶颈,是客户端自己堵死了。
控制并发数用
+
,别用
循环直接起 goroutine
写个
用
做信号通道,N 即最大并发数(如 200)
每个请求前
配合
等待全部完成,别依赖
漏掉 channel 泄露或 wg.Add/Wait 不配对,会导致程序提前退出或永远 hang 住。
立即学习
“
go语言免费学习笔记(深入)
”;
统计响应时间得用
和
,别依赖日志打点或服务端返回
压测关注的是「客户端视角的真实耗时」,包括 DNS 解析、TCP 握手、TLS 协商、发送、等待、接收全过程。服务端日志里的耗时只反映处理阶段,且受时钟不同步影响。实操必须在 client 侧精确采集:
在
前调用
请求返回后立刻算
把所有
存进 slice 或流式计算 p95/p99,别等压完再从日志 grep
忽略重定向、忽略错误请求(如
)都得单独判断,否则统计失真——比如超时请求被记成 0ms,p99 就完全没意义。
解析 JSON 响应失败时,
报
很可能是服务端返回了 HTML 错误页
压测中常遇到
或更模糊的
,这不是代码 bug,而是目标服务在高压下返回了 502/503 页面(比如 Nginx 默认错误页),内容是 HTML,却仍带
。排查步骤:
先打印原始
前 200 字节,看是不是
检查
,非 2xx/3xx 响应一律跳过 JSON 解析
加一层
防御性判断
这个坑特别隐蔽:本地跑得通,一上压测环境就崩,因为只有高并发才触发网关降级。不验证响应体类型,解析逻辑会静默失败,指标全乱。
net/httphttp.DefaultClienthttp.Clienthttp.DefaultClientTimeoutTransportMaxIdleConnsMaxIdleConnsPerHostTimeout10 * time.SecondTransport.MaxIdleConnsTransport.MaxIdleConnsPerHostTransport.IdleConnTimeoutsync.WaitGroupchannelforfor i := 0; i 看似简单,实则危险:瞬间拉起上万个 goroutine,内存暴涨、调度开销大,还可能触发系统级限制(如文件描述符耗尽)。正确做法是用固定 worker 池控流:make(chan struct{}, N)sem ,结束后 <-semsync.WaitGrouptime.Sleeptime.Now()time.Since()http.Do()start := time.Now()latency := time.Since(start)latencystatus != 200json.Unmarshalinvalid characterjson: cannot unmarshal string into Go value of type map[string]interface{}invalid characterContent-Type: application/jsonresp.Bodyresp.StatusCodestrings.HasPrefix(string(body), "<")