1. 为什么需要连接池 1.1 数据库连接的代价 创建一条数据库连接是昂贵 的操作:
TCP 三次握手(~1-3ms,跨可用区更长) TLS/SSL 握手(如有,~5-20ms) 数据库认证(密码验证、权限查询) 内存分配(数据库端为连接分配会话内存) 无连接池 vs 连接池:
无连接池:
每次请求 ──→ 新建连接 ──→ 执行 SQL ──→ 关闭连接
↑ ↓
└──── 每次 5-20ms ────┘
连接池:
初始化:创建 10 条连接放入池中
每次请求 ──→ 从池获取连接(< 1ms)──→ 执行 SQL ──→ 归还连接
↑ ↓
└────────── 复用,无创建开销 ──────────┘
1.2 连接池核心收益 收益 说明 降低延迟 避免每次请求建立连接的开销 资源控制 限制最大连接数,防止数据库过载 连接复用 减少数据库端会话资源消耗 稳定性 预热连接、健康检查保障可用性
2. 连接池核心参数 2.1 参数详解 参数 作用 建议值 minimumIdle 最小空闲连接数 5-10(保持热连接) maximumPoolSize 最大连接数 20-50(取决于 DB 配置) connectionTimeout 获取连接最大等待时间 30s idleTimeout 空闲连接超时回收 10min maxLifetime 连接最大存活时间 30min(短于 DB wait_timeout) keepaliveTime 保活检查间隔 5min
2.2 最大连接数设置 公式:连接池大小 = ((核心数 × 2) + 有效磁盘数)
更精确的计算:
连接数 = (CPU 核心数 × 2) + 磁盘 spindle 数
示例(HikariCP 作者建议):
4 核服务器 → 约 10 个连接即可获得最大吞吐
连接数再多,由于上下文切换和锁竞争,吞吐反而下降
生产环境经验:
单机应用:10-20 连接
微服务集群(10 实例 × 10 连接):需 DB 支持 100+ 连接
MySQL max_connections 默认 151,需按规模调整
3. 主流连接池对比 3.1 HikariCP(推荐) “Fast, simple, reliable. Zero overhead.”
特性 HikariCP 特点 极致性能、代码精简、无额外功能 性能 最快(benchmark 中远超 Druid/c3p0) 监控 基础 JMX 指标 防护 无 SQL 注入检测、无防火墙
// Spring Boot 默认连接池(2.0+)
HikariConfig config = new HikariConfig ();
config . setJdbcUrl ( "jdbc:mysql://localhost:3306/shop" );
config . setUsername ( "user" );
config . setPassword ( "pass" );
config . setMaximumPoolSize ( 20 );
config . setMinimumIdle ( 5 );
config . setConnectionTimeout ( 30000 );
config . setIdleTimeout ( 600000 );
config . setMaxLifetime ( 1800000 );
config . setLeakDetectionThreshold ( 60000 ); // 连接泄露检测:60s未归还则记录
HikariDataSource dataSource = new HikariDataSource ( config );
3.2 Druid(阿里开源) “为监控而生的数据库连接池”
特性 Druid 特点 功能丰富、监控完善、内置 SQL 防火墙 性能 接近 HikariCP 监控 完整 Web UI、SQL 统计、慢查询 防护 SQL 注入检测、黑白名单、WallFilter
// Druid 配置示例
DruidDataSource dataSource = new DruidDataSource ();
dataSource . setUrl ( "jdbc:mysql://localhost:3306/shop" );
dataSource . setInitialSize ( 5 );
dataSource . setMinIdle ( 5 );
dataSource . setMaxActive ( 20 );
dataSource . setMaxWait ( 30000 );
// 开启监控
DruidStatManagerFacade . getInstance (). getDataSourceStatDataList ();
// SQL 防火墙
WallConfig wallConfig = new WallConfig ();
wallConfig . setSelectAllow ( true );
wallConfig . setDeleteAllow ( false ); // 禁止 DELETE
3.3 连接池对比 维度 HikariCP Druid c3p0 DBCP2 性能 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐ 监控能力 ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ SQL 防护 ❌ ✅ ❌ ❌ 代码体积 极小 中等 中等 小 活跃度 高 高 低 中 Spring Boot 默认 ✅ (2.0+) ❌ ❌ ❌
4. 连接泄露与治理 4.1 连接泄露场景 // ❌ 错误:未关闭连接
public void badMethod () {
Connection conn = dataSource . getConnection ();
// 执行业务逻辑...
// 忘记 conn.close()!
}
// ✅ 正确:try-with-resources
public void goodMethod () {
try ( Connection conn = dataSource . getConnection ();
PreparedStatement ps = conn . prepareStatement ( SQL )) {
// 执行 SQL
} catch ( SQLException e ) {
// 异常处理
}
// 自动关闭 Connection 和 Statement
}
4.2 连接泄露检测 // HikariCP 泄露检测
config . setLeakDetectionThreshold ( 60000 ); // 60s
// 检测到泄露时输出:
// Apparent connection leak detected, owning stack trace follows:
// java.lang.Thread.getStackTrace(Thread.java:1559)
// com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)
// com.example.Service.query(Service.java:45)
5. 生产实践 5.1 连接池配置模板 # application.yml (Spring Boot)
spring :
datasource :
url : jdbc:mysql://mysql-service:3306/shop?useSSL=true
username : ${DB_USER}
password : ${DB_PASS}
driver-class-name : com.mysql.cj.jdbc.Driver
hikari :
pool-name : ShopHikariPool
minimum-idle : 5
maximum-pool-size : 20
connection-timeout : 30000
idle-timeout : 600000
max-lifetime : 1800000
leak-detection-threshold : 60000
connection-test-query : SELECT 1
validation-timeout : 5000
5.2 监控指标 指标 说明 告警阈值 Active Connections 活跃连接数 > maximumPoolSize × 80% Idle Connections 空闲连接数 < minimumIdle Pending Threads 等待连接的线程数 > 0 持续 1 分钟 Total Connections 总连接数 异常波动 Connection Acquired Time 获取连接耗时 > 100ms
延伸阅读 继续阅读
探索更多技术文章 浏览归档,发现更多关于系统设计、工具链和工程实践的内容。