跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

golang如何实现API压测工具_golang API压测工具实现攻略

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

相关文章