4. 连接池关键指标:活跃连接数、空闲连接数、等待队列长度、连接超时率、连接泄漏率

在 OAuth2.0 授权码模式与客户端凭证模式中,网关或微服务通常通过连接池与授权服务器(Authorization Server, AS)或资源服务器(Resource Server, RS)交互。连接池的健康状态直接决定认证链路的吞吐与稳定性。本章定义五项核心水位指标,并给出巡检阈值与故障判定逻辑。

4.1 指标定义与业务含义

指标名称 符号 定义 正常范围(参考)
活跃连接数 Active 当前正在被线程持有、执行 HTTP 请求的连接数量 ≤ 池最大容量 × 80%
空闲连接数 Idle 已建立但未被使用的连接,可被快速借用 ≥ 1 且 ≤ 池最大容量 × 30%
等待队列长度 Pending 因无可用连接而阻塞等待的线程数 0(偶发 ≤ 5 可接受)
连接超时率 Timeout% 单位时间内获取连接超时的次数 / 总请求次数 < 1%
连接泄漏率 Leak% 未归还连接占已创建连接的比例(通过弱引用追踪) 0%(容忍 < 0.1%)
巡检要点: 五项指标需联合分析。例如:Active 未满但 Pending 持续增长,通常意味着连接被长时间阻塞(慢响应或死锁);Idle 长期为 0 且 Timeout% 上升,说明池容量不足或连接回收策略失效。

4.2 指标关联与水位模型

连接池水位可抽象为三层状态机。下图展示从正常到故障的演进路径:

连接池水位状态机 正常水位 Active ≤ 80% Idle ≥ 1, Pending = 0 Timeout% < 1% 告警水位 Active > 80% Pending 1~10 Timeout% 1%~5% 故障水位 Active = 100% Pending > 10 Timeout% > 5% 或 Leak% > 0.1% 巡检动作说明 1. 正常 → 告警:触发扩容或限流,检查后端 AS/RS 响应时间。 2. 告警 → 故障:立即 dump 线程栈,分析连接未释放原因。 3. 故障恢复:重启连接池或摘除异常节点,确认 Leak% 归零。

4.3 关键指标采集方式

以 Java 生态中最常用的 Apache HttpClient 和 OkHttp 为例,展示如何通过 JMX 或内置 Metrics 获取五项指标:

4.3.1 Apache HttpClient(PoolingHttpClientConnectionManager)

// 通过 JMX 或直接调用 PoolStats
PoolStats stats = connManager.getTotalStats();
int active = stats.getLeased();          // 活跃连接数
int idle   = stats.getAvailable();       // 空闲连接数
int pending= stats.getPending();         // 等待队列长度

// 超时率需自行计数
long timeoutCount = metricRegistry.counter("http.pool.timeout").getCount();
long totalCount   = metricRegistry.counter("http.pool.total").getCount();
double timeoutRate = (totalCount == 0) ? 0.0 : (double) timeoutCount / totalCount;

// 泄漏率通过 WeakRef 追踪
long createdCount = connManager.getTotalStats().getMax();
long returnedCount = ...; // 在连接归还时计数
double leakRate = (createdCount == 0) ? 0.0 :
    (double) (createdCount - returnedCount) / createdCount;

4.3.2 OkHttp(ConnectionPool)

ConnectionPool pool = client.connectionPool();
int idleCount = pool.idleConnectionCount();   // 空闲连接数
int totalCount = pool.connectionCount();      // 总连接数(活跃+空闲)
int active = totalCount - idleCount;          // 活跃连接数

// OkHttp 不直接暴露等待队列,需通过 Dispatcher 的 queuedCalls() 间接判断
int pending = client.dispatcher().queuedCallsCount();
注意: OkHttp 默认不提供连接超时率与泄漏率的内置计数器。生产环境建议通过 EventListener 或 Interceptor 手动埋点,采集 connectFailed 与 connectionReleased 事件。

4.4 连接泄漏检测与定位

连接泄漏是 OAuth2.0 场景中最隐蔽的故障。泄漏通常由以下原因引起:

  • 未关闭响应流: 读取 HttpResponse.getEntity().getContent() 后未调用 close()。
  • 异常路径未归还: try-catch 块中未在 finally 释放连接。
  • 连接借出超时: 设置了 setConnectionRequestTimeout() 但未处理超时异常后的连接回收。

下图展示泄漏检测的典型流程:

连接泄漏检测流程 创建连接 注册 WeakRef 归还连接 GC 未回收 触发告警 检测逻辑:连接创建时注册 WeakRef 到追踪队列;若连接未在超时时间内归还且 GC 后 WeakRef 仍存活,判定为泄漏。

4.5 巡检脚本示例(Prometheus + Grafana)

以下 PromQL 查询可直接用于 Grafana 面板,监控连接池水位:

# 活跃连接数占比
rate(http_client_connections_active[1m]) / http_client_connections_max

# 等待队列长度(需 exporter 暴露 gauge)
http_client_connections_pending

# 连接超时率(rate 计算)
rate(http_client_requests_timeout_total[5m]) / rate(http_client_requests_total[5m])

# 连接泄漏率(基于自定义 metric)
rate(http_client_connections_leaked_total[5m]) / rate(http_client_connections_created_total[5m])
最佳实践: 在 OAuth2.0 网关层,建议将连接池巡检纳入 P1 告警。当 Pending > 0 持续超过 30 秒,或 Timeout% > 2% 时,立即触发容器健康检查失败,由编排层自动重启异常 Pod。