k6压测需避免本地资源自爆,应合理配置并发策略、禁用连接复用以暴露真实瓶颈,并通过P95/P99延迟评估用户体验。

为什么不能直接用 http.Get 写个 for 循环压测
这不是“并发测试”,是本地资源自爆现场。每次 http.Get 都新建一个 http.Client,而默认 Transport 的 MaxIdleConns 是 0,等于每请求都建新 TCP 连接。后果很实在:
• TIME_WAIT 连接数暴涨,本机端口几秒耗尽
• 同一域名反复 DNS 查询,延迟毛刺明显
• HTTPS 请求频繁 TLS 握手,CPU 和 RT 都被拖垮
• 并发稍大就卡在 dial tcp: lookup xxx: no such host 或 too many open files
这不是服务扛不住,是你本机 ulimit 和连接管理没配好。
k6 脚本里怎么控制真实并发与请求节奏
k6 的 vus(虚拟用户)不是“线程数”,而是独立运行的 JS 执行上下文,每个 VU 持续循环执行 default 函数。关键在于:不靠 for + go 控并发,而是靠 executor 策略和参数组合。
• 想测稳定吞吐量?用 constant-vus + duration,比如 k6 run --vus 200 --duration 2m script.js
• 想找系统拐点?用 ramping-vus,逐步加压:--stage 30s:50,1m:200,30s:50
• 想模拟突发流量?用 per-vu-iterations + exec 控制单 VU 行为,避免所有 VU 同时发请求造成脉冲
• 别裸写 sleep(1) 模拟间隔——它只停当前 VU,不影响其他;真正控频得靠 rate 类 executor 或自己用 time.sleep() 加锁协调(极少需要)
HTTP 压测中如何绕过连接复用干扰真实 QPS
Go 默认 http.DefaultClient 复用 TCP 连接,而 Gin/Echo 等框架在连接复用下会隐藏连接池瓶颈。压测时若不显式断连,QPS 数值虚高,无法反映真实并发承载力。
• 对 HTTP/1.1 接口:在 k6 脚本里加请求头 headers: { 'Connection': 'close' }
• 对 HTTP/2 接口:k6 默认启用 HTTP/2,但某些服务反向代理(如 Nginx)可能未开启 h2 支持,导致降级失败;可加 http.setHTTP2(false) 强制走 HTTP/1.1
• 若目标服务启用了长连接且你就是要测连接池表现,那就别关复用——但必须确认后端 max_connections、keepalive_timeout 等配置已调优,否则测的是中间件限制而非 Go 服务本身
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
从 k6 输出里提取 P95/P99 延迟别只看 mean
k6 默认输出的 http_req_duration mean 值毫无意义,它掩盖长尾。P95/P99 才决定用户体验是否崩塌。
• 直接跑命令时加 --out json=output.json,再用 jq '.metrics.http_req_duration.values.p95' 提取
• 在脚本里用 check() + 自定义指标:check(res, { 'p95 p95 ,配合 <code>thresholds 配置自动失败
• 注意:k6 的分位数统计基于所有成功请求(status 2xx/3xx),超时或网络错误不计入延迟分布,所以务必设好 timeout 参数(如 http.get(url, { timeout: '3s' })),否则慢请求被丢弃,P99 被人为拉低
• 如果要和 vegeta 对齐,注意 k6 的 p95 是毫秒单位,vegeta 的 .latencies.p95 是纳秒单位,别直接比数值
立即学习“go语言免费学习笔记(深入)”;
真实压测里最常被跳过的环节,是验证目标服务是否开了pprof 并在压测中采集火焰图。没它,你永远不知道延迟毛刺到底是 GC、锁竞争,还是某条 SQL 慢查询。


















