长连接本身无qps概念,真正需监控的是单位时间新建连接数(rate(ws_connections_created_total[1m]))、活跃连接数(gauge)及异常断连率;须在连接建立点(如upgrade成功后)用counter埋点,禁用gauge计算速率。

长连接本身没有QPS概念,所谓“长连接QPS”其实是误用术语——你真正要监控的,是单位时间内新建立的长连接数(即连接创建速率),以及这些连接的活跃状态、生命周期和异常断连情况。
为什么直接用 rate(http_requests_total[1m]) 算不出长连接QPS
因为 http_requests_total 统计的是 HTTP 请求次数,而 WebSocket、gRPC streaming、HTTP/2 Server Push 等长连接场景中,一个连接会承载多个逻辑请求,甚至持续数小时不发新请求。Prometheus 默认抓取的 http_requests_total 根本不感知连接建立动作。
- 你看到的“连接暴涨”,大概率只是
go_goroutines上升,但它混杂了定时器、IO wait、业务协程等,无法区分真实连接 - 若没手动定义连接指标,
/metrics里压根不会有ws_connections_created_total或grpc_streams_active这类指标 - 即使定义了 Counter,也得确保在
conn.Accept()、upgrader.Upgrade()、stream.Send()等实际连接建立点调用.Inc(),而不是在 handler 入口
必须用 NewCounterVec 记录连接创建事件,而非 NewGaugeVec
虽然连接数是瞬时值,但“每秒新建多少连接”是典型的速率型指标,需要用 Counter + rate() 计算,不是 Gauge 的当前快照。
-
NewCounterVec:记录每次连接建立事件,如ws_connections_created_total{protocol="websocket",path="/stream"},再用rate(ws_connections_created_total[1m])得到 QPS -
NewGaugeVec:只适合统计当前活跃连接数,如ws_connections_active{status="active"},它不能被rate()求导,也不能反映创建频次 - 标签设计要包含
protocol(ws/grpc/http2)、path(路由路径)、client_type(web/app/iot)——否则聚合后无法定位是哪个端或哪个接口引发连接洪峰
连接建立点埋点容易漏掉的三个位置
长连接的创建常发生在标准 HTTP handler 之外,尤其在底层网络层或框架封装后,容易漏埋点。
- WebSocket:不是
router.GET("/ws")进入 handler 时算,而是upgrader.Upgrade(w, r, nil)成功返回后才应connCreated.Inc() - gRPC streaming:不是
func (s *Server) StreamData(...)函数入口,而是stream.Context().Done()尚未触发、且首次收到stream.Recv()数据时才代表流已激活 - HTTP/2 Server Push:需在
responseWriter.Push()调用成功后计数,且注意该操作可能失败(如客户端禁用 push),要包裹if err == nil判断
Grafana 查询与看板配置关键项
单纯暴露指标没用,Grafana 里查错 PromQL 就等于白搭。以下字段必须核对:
- 数据源必须指向你自定义 Registry 的
/metrics端点,不是默认的promhttp.Handler()—— 后者只暴露 runtime 指标,不含你的连接指标 - QPS 面板用
rate(ws_connections_created_total{job="my-go-service"}[1m]),别漏job标签过滤,否则多实例数据会叠加 - 活跃连接数面板用
sum by (protocol, path) (ws_connections_active),配合max_over_time()观察峰值,比瞬时值更有参考性 - 异常断连率建议加告警:
rate(ws_connections_closed_total{reason!="normal"}[5m]) / rate(ws_connections_created_total[5m]) > 0.05
最易忽略的一点:所有连接创建计数必须在 defer 释放前完成,且不能放在 goroutine 里异步执行——Go 的 HTTP handler 返回后连接可能已被回收,此时再 Inc 已无意义。











