用net/http+sync/atomic实现压测脚本需设自定义http.client(timeout、maxidleconns≥2000)、用atomic计数避免竞态,通过context控制各阶段超时,配合固定并发goroutine池与缓冲channel确保准确统计。

用 net/http + sync/atomic 快速写一个可计数的压测脚本
Go 写压测脚本不一定要上 vegeta 或 ghz,简单接口吞吐量摸底时,自己写个几十行的并发请求+计数器更可控、更容易调试。
核心是避免用全局变量做计数(竞态),也别用 sync.Mutex 锁太重——sync/atomic 足够快且安全。
-
http.DefaultClient默认复用连接,但要显式设置Transport的MaxIdleConns和MaxIdleConnsPerHost,否则默认只保持 2 个空闲连接,压不起来 - 用
time.AfterFunc或单独 goroutine 控制测试时长,别靠循环 sleep 算时间,误差大 - 请求体如果是 JSON,记得设
Content-Type: application/json,漏了服务端可能 415 - 错误不 panic,统一收集到
atomic.AddInt64(&failures, 1),最后看失败率
为什么 goroutines 数设成 100 却压不出 100 QPS?
QPS 不等于并发数。100 个 goroutine 同时发请求,但每个请求耗时 200ms,理论极限只有 500 QPS(100 / 0.2),实际还受网络延迟、服务端处理瓶颈、DNS 解析阻塞影响。
真正卡点常在客户端自身:DNS 缓存没开、TLS 握手没复用、连接池打满、甚至本地文件描述符耗尽(ulimit -n 默认常为 1024)。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 加
client.Transport.DialContext用net.Dialer{KeepAlive: 30 * time.Second}开启 keepalive - DNS 查找慢?加
client.Transport.DialContext = fastDialer,或直接用 IP 测试排除 DNS 干扰 - 观察
netstat -an | grep :端口 | wc -l,如果 ESTABLISHED + TIME_WAIT 接近 ulimit,就是连接打满了 - 别盲目堆 goroutine,先固定并发数,调低
time.Sleep间隔看能否线性提升 QPS,再决定是否加压
http.Client 超时设置必须分三层
很多人只设 Timeout,结果 DNS 卡住 30 秒才超时,或者 TLS 握手卡死,整个压测停住。Go 的 http.Client 超时必须拆开控制:
-
Timeout:整个请求生命周期(含 DNS、连接、写请求、读响应),建议设为10 * time.Second以上,仅作兜底 -
Transport的IdleConnTimeout和TLSHandshakeTimeout单独设(如 5s),防止连接池僵死或握手挂起 - 真正要控的是
context.WithTimeout传给client.Do(req.WithContext(ctx)),这样 DNS 和 dial 阶段也能被 cancel - 注意:
Timeout和 context 超时同时存在时,以先发生的为准;但没配 context 时,dial 阶段仍可能卡住
真实压测中 status code 200 却吞吐掉得厉害?查这三处
服务端返回 200 不代表健康。很多压测脚本只看 status,忽略 body 内容、header 字段、响应时间分布,导致误判。
- 加一行
if len(resp.Body) == 0或resp.Header.Get("X-App-Status") != "ok"做业务级校验,避免服务端降级返回空 200 - 用
atomic.AddInt64(&totalBytes, int64(resp.ContentLength))统计真实流量,突增可能意味着返回了错误的大体积 fallback 数据 - 记录 p95/p99 响应时间(用
sort.Float64s+ 切片索引),比平均值更能暴露长尾问题;单次请求 >2s 就该记日志,别只统计总数 - 别信“稳定跑满 CPU”,Go runtime 的
GOMAXPROCS默认等于核数,压测进程若没绑核或被调度抢占,CPU 利用率虚高但实际 QPS 上不去
压测不是跑数字,是验证链路里每一环的承受边界。连不上、连上了但慢、连上了也快但错数据——这三个层次的问题,得靠不同粒度的日志和指标分开看。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










