go test -bench不能测发布后模块qps,因其不走真实网络栈;必须用hey或vegeta发起真实tcp请求,禁用keepalive以暴露服务端time_wait、accept队列等瓶颈,手写脚本需显式配置http.transport参数并用time.ticker控稳态qps。

别用 go test -bench 测发布后的模块 QPS——它不走网络栈、不建真实连接、不触发服务端 accept 队列,结果毫无参考价值。
用 hey 或 vegeta 打真实 TCP 请求
发布后模块(比如 HTTP 接口)的 QPS 必须靠真实客户端发起请求来验证,核心是绕过所有 mock 和内存模拟,直击服务端真实瓶颈。
-
hey最适合快速验证:下载预编译二进制(wget https://storage.googleapis.com/hey-releases/hey_linux_amd64),避免go install卡在代理上 - 命令示例:
hey -n 5000 -c 100 -q 10 http://your-service:8080/api/v1/health,其中-c是并发 worker 数,-q是每 worker 每秒请求数,理论 QPS ≈-c × -q,但实际受服务端吞吐限制 -
vegeta更适合带节奏压测:echo "GET http://your-service:8080/api/v1/health" | vegeta attack -rate=100 -duration=30s -timeout=5s -insecure,注意必须加-insecure(若用 HTTPS)和显式-timeout - 两者都建议加
-disable-keepalive(vegeta默认关闭,hey需手动加),否则连接复用会掩盖服务端TIME_WAIT积压或accept队列溢出问题
手写压测脚本时,http.Transport 四个参数必须显式设为 0
如果你需要自定义逻辑(比如带鉴权头、分路径打点),手写 Go 脚本比命令行更灵活,但极易因默认配置失真——默认 http.Client 会复用 DNS、TLS 会话和空闲连接,根本不是“新用户访问”场景。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 必须设置:
MaxIdleConns = 0、MaxIdleConnsPerHost = 0、IdleConnTimeout = 0、ForceAttemptHTTP2 = false - HTTPS 测试环境建议加:
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},跳过证书校验节省开销 - 错误现象包括:
dial tcp: lookup xxx: no such host(DNS 缓存干扰)、too many open files(连接未及时关闭)、延迟毛刺剧烈(TLS 握手堆积) - 别用裸
go http.Get()启一堆 goroutine——那是瞬发洪峰,测的是你本机调度器和文件描述符上限,不是服务承载力
QPS 稳态 ≠ 并发数,要用 time.Ticker 控节奏
真实用户是按固定频率发请求的(如 100 QPS),不是同时发 100 个再等 1 秒。裸循环或 semaphore 只能控峰值,并不能模拟稳态流量。
- 用
time.Ticker替代time.Sleep:精度更高,且能自动补偿单次请求耗时波动 - 推荐生产者-消费者模型:
reqChan := make(chan struct{}, tps)(缓冲区大小设为目标 QPS),一个 ticker goroutine 定期往 channel 写信号,N 个 worker 从 channel 读取并执行请求 -
concurrency应 ≥tps,否则 channel 会积压;但也不宜远大于tps,否则大量 goroutine 空转浪费调度资源 - 务必用
sync.WaitGroup等待所有请求完成,避免主 goroutine 提前退出导致统计漏量
发布后测 QPS 的关键,从来不是“能不能打出高数字”,而是“打出的数字是否暴露了服务端真实瓶颈”。连接池打满、accept 队列溢出、TLS 握手阻塞——这些全藏在禁用复用后的连接风暴里。漏掉这一步,等于没测。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










