压测时必须暴露的3类Gin基础指标是http_request_duration_seconds(Histogram类型)、http_requests_total(带method/status/path标签的Counter)和go_goroutines;否则无法准确计算P95/P99延迟、区分接口QPS瓶颈及发现goroutine泄漏。

压测时必须暴露的 3 类 Gin 基础指标
不暴露这些,Prometheus 抓不到真实请求负载,压测结果就不可信。Gin 本身不自动打点,得靠 prometheus/client_golang 手动注册。
重点不是“有没有指标”,而是“指标是否覆盖压测关键链路”:
-
http_request_duration_seconds:必须用Histogram类型,否则算不出 P95/P99 延迟;别用Summary,它在高并发下分位数计算不准且不支持聚合 -
http_requests_total:带method、status、path标签的Counter,否则无法区分是哪个接口拖垮了整体 QPS -
go_goroutines:从expvar或runtime暴露,压测中 goroutine 数持续上涨,大概率是中间件没正确释放 context 或 channel 泄漏
Gin 中间件里埋点容易漏掉的 2 个坑
很多人在 AuthFilter 或日志中间件里加计数,但忘了:请求被 panic 拦截、或提前 c.Abort() 时,http_requests_total 不会自增,http_request_duration_seconds 也不会打点——这会导致压测报告里“成功请求数”虚高,“错误率”偏低。
正确做法是统一用 defer 包裹打点逻辑,且在 recover 和 Abort 后也强制记录:
func MetricsMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
c.Next() // 执行后续 handler
<pre class="brush:php;toolbar:false;"> // 即使 c.Abort() 或 panic,c.Writer.Status() 仍可读
status := c.Writer.Status()
duration := time.Since(start).Seconds()
httpRequestDuration.WithLabelValues(
c.Request.Method,
strconv.Itoa(status),
c.HandlerName(),
).Observe(duration)
httpRequestsTotal.WithLabelValues(
c.Request.Method,
strconv.Itoa(status),
c.HandlerName(),
).Inc()
}}
压测期间 Goroutine 泄漏的典型信号
单纯看 go_goroutines 数值没意义,要结合压测节奏看趋势。如果 QPS 稳定但 goroutine 数持续单边上升,基本可判定泄漏。
常见泄漏点:
- 用了
time.AfterFunc但没绑定 request context,压测结束后定时器还在跑 - 中间件里启了 goroutine 调用下游(比如异步发消息),但没用
c.Request.Context()做 cancel 传播 - 自定义
sync.Pool对象没重置状态,导致下次复用时隐式持有旧请求上下文
验证方式:压测前后各执行一次 curl http://localhost:8080/debug/pprof/goroutine?debug=2,对比栈帧里重复出现的 handler 路径。
为什么 /metrics 端点本身不能参与压测
压测工具(如 wrk、hey)如果把 /metrics 加进目标 URL 列表,会污染指标数据:http_requests_total{path="/metrics"} 会暴涨,掩盖真实业务接口的请求分布。
更严重的是,Prometheus 默认的 promhttp.Handler() 是同步阻塞实现,高并发抓取时可能拖慢整个 HTTP server 的响应能力——尤其当指标量大(比如注册了上百个自定义 metric)时,/metrics 接口延迟会跳到几百毫秒。
安全做法:
- 压测期间禁用 Prometheus 抓取,或改用 pushgateway 主动推送
- 给
/metrics单独开一个非业务端口(如:9091),和主服务隔离 - 用
promhttp.HandlerFor(registry, promhttp.HandlerOpts{Timeout: 10 * time.Second})加超时保护
指标采集和压测必须物理隔离,这是很多团队在 TPS 突降时才意识到的关键边界。


















