压测前必须确认goroutine泄漏风险,需检查空载goroutine数、显式设置HTTP超时、开启服务读写超时、优化锁竞争、绑核运行并监控GC与内存。

压测前必须确认 goroutine 泄漏风险
Go 程序压测失真,八成是因为 goroutine 没回收干净。比如用 http.DefaultClient 发请求但没设 Timeout,后端响应慢或挂掉时,goroutine 会卡在 Read 状态长期存活;又或者用 time.After 配合 select 但没处理 default 分支,导致协程阻塞等待超时——这些都会让压测过程中 goroutine 数持续上涨,掩盖真实吞吐瓶颈。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 压测前跑一次
go tool pprof http://localhost:6060/debug/pprof/goroutine?debug=2,确认空载时goroutine数稳定(通常几十个以内) - 所有 HTTP 客户端必须显式设置
Timeout或用context.WithTimeout - 避免裸写
for { select { case ,确保有退出路径或默认分支 - 压测中用
runtime.NumGoroutine()打点监控,突增即停测排查
选对压测工具:wrk vs go-wrk vs 自研 goroutine flood
wrk 是 C 写的,单机压测能力极强,但它不理解 Go 的 HTTP/2、gRPC 或自定义 header 透传逻辑;go-wrk 能复用 Go 的 net/http 栈和 context,适合验证服务端 Go 代码的真实并发行为,但单机并发上限受 GOMAXPROCS 和系统文件描述符限制;而“自研 goroutine flood”(比如起 10k 个 go req())看似简单,却极易因未控速、无连接复用、无错误抑制,瞬间打崩客户端自身。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 验证服务端吞吐/延迟:优先用
go-wrk -t 4 -c 200 -n 10000 -H "X-Trace-ID: test",它能走 Go 原生 TLS 和 HTTP/2 - 测长连接或流式接口(如 SSE、gRPC streaming):必须用 Go 写压测脚本,复用
http.Client.Transport并设MaxIdleConnsPerHost - 避免直接
for i := 0; i ,改用带限速的semaphore或worker pool
关键指标怎么看:不是 QPS 越高越好
Go 服务压测时,只盯着 QPS 容易误判。真正要盯的是三组数字的联动关系:客户端观测的 latency 95%、服务端 runtime.ReadMemStats().AllocBytes 增长速率、以及 pprof CPU 中 runtime.selectgo 或 net.(*pollDesc).waitRead 占比。比如 QPS 上到 5000,但 latency 95% 从 20ms 涨到 800ms,同时 AllocBytes/sec 翻倍——这说明 GC 开始拖累,不是 CPU 或 IO 瓶颈。
云模块_YunMOK网站管理系统采用PHP+MYSQL为编程语言,搭载自主研发的模块化引擎驱动技术,实现可视化拖拽无技术创建并管理网站!如你所想,无限可能,支持创建任何网站:企业、商城、O2O、门户、论坛、人才等一块儿搞定!永久免费授权,包括商业用途; 默认内置三套免费模板。PC网站+手机网站+适配微信+文章管理+产品管理+SEO优化+组件扩展+NEW Login界面.....目测已经遥遥领先..
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 用
go tool pprof -http=:8080 cpu.pprof查看热点,若runtime.mallocgc> 15%,优先调GOGC或减少小对象分配 - 观察
/debug/pprof/heap?gc=1,对比两次采样间inuse_objects是否线性增长(泄漏信号) - HTTP 服务务必打开
http.Server.ReadTimeout和WriteTimeout,否则慢请求会堆积goroutine却不被latency统计捕获
生产环境压测最容易忽略的调度细节
本地 GOMAXPROCS=8 压出 1w QPS,上线后 GOMAXPROCS=32 反而降为 7k——问题常出在锁竞争或 OS 级调度抖动。比如用 sync.Mutex 保护一个高频更新的计数器,CPU 核数翻倍后争抢更剧烈;又或者 net.Conn 的读写缓冲区太小,在高并发下频繁触发 epoll_wait 唤醒,导致 M:N 调度器频繁切换 P。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 高频共享状态优先用
atomic,次选用sync/atomic.Value,慎用sync.RWMutex - HTTP 服务启动时显式调
http.Server.SetKeepAlivesEnabled(true),并增大net/http.Transport.MaxIdleConnsPerHost - 压测时用
taskset -c 0-7 ./server绑核运行,排除 NUMA 和跨 CPU 缓存失效干扰
压测不是比谁数字大,而是找出那个最先绷紧的弦——可能是 GC、是锁、是网络栈缓冲区,也可能是你忘了关 debug 日志里的 fmt.Printf。










