连接池是任何数据库访问层的性能基石。一个配置得当的连接池,可以让系统在流量高峰期稳定运行;而一个使用默认参数或随意设置的连接池,则可能成为全链路中最隐蔽的瓶颈。Spring Boot 生态中,HikariCP 是默认内嵌的高性能连接池,而 Druid 则因其丰富的监控与防护能力在企业中广泛使用。本节将围绕它们的核心参数、调优思路和实战配置展开。
13.1.1 HikariCP:轻量与极速的代表
HikariCP 主打“零开销”的极致性能,Spring Boot 2.x 起已将其设为默认连接池。它的设计理念是精简代码路径、避免不必要的锁竞争,因此在大多数场景下,保持默认配置即可获得优秀表现。但仍有几个关键参数值得根据实际环境调整。
1. 核心配置参数
| 参数 | 默认值 | 说明 |
|------|--------|------|
| spring.datasource.hikari.connection-timeout | 30000 (ms) | 连接等待超时。超过此时间仍未获取到连接会抛出异常。需结合业务容忍度调整。 |
| spring.datasource.hikari.maximum-pool-size | 10 | 最大连接数。并非越大越好,受数据库最大连接数和硬件资源限制。 |
| spring.datasource.hikari.minimum-idle | 10(等于最大连接数) | 最小空闲连接数。HikariCP 默认会维持与最大连接数相同的空闲连接,以获得恒定响应性能。 |
| spring.datasource.hikari.idle-timeout | 600000 (ms) | 空闲连接最大存活时间。仅当 minimum-idle 小于 maximum-pool-size 时生效。 |
| spring.datasource.hikari.max-lifetime | 1800000 (ms) | 连接最大存活时间。应比数据库的 wait_timeout(MySQL 默认 8 小时)短,防止使用已被数据库关闭的连接。 |
| spring.datasource.hikari.connection-test-query | 无(依赖于 JDBC4 的 isValid()) | 连接有效性测试查询。当驱动程序支持 Connection.isValid() 时无需配置,否则需提供,如 SELECT 1。 |
2. 生产环境推荐配置(MySQL 为例)
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: app
password: secret
hikari:
connection-timeout: 5000
maximum-pool-size: 20
minimum-idle: 10
idle-timeout: 300000
max-lifetime: 1200000
leak-detection-threshold: 10000 # 连接泄漏检测,10秒
pool-name: MyAppPool
调优思路:
- 最大连接数:先估算单服务实例的并发请求量。假设每个关键数据库操作平均耗时 50ms,单连接 QPS 约 20。若单实例需要支撑 400 QPS,理论需要 20 个连接。实际应结合压测结果微调,留出 15%~20% 的余量。
- 连接超时:微服务调用的延迟容忍度较低时,可将
connection-timeout调至 3~5 秒,快速失败,避免线程堆积。 - 泄漏检测:
leak-detection-threshold能在开发/测试阶段及早发现未归还的连接。生产环境若启用,需设置一个明显大于正常操作时间的值(如 10~30 秒),以免误报。 - 数据库连接限制:确保连接池总和(所有服务实例的最大连接数之和)不超过数据库的
max_connections,否则会导致数据库拒绝连接。
13.1.2 Druid:功能全面的连接池
Druid 由阿里巴巴开源,定位不仅是连接池,更是一个自带监控、SQL 解析与防护的“数据源中间件”。当项目有 SQL 监控、慢 SQL 记录、防 SQL 注入等需求时,Druid 是首选方案。
1. 核心配置参数
Druid 的参数更为丰富,以下几类是重中之重:
- 基本资源控制:
initialSize、minIdle、maxActive、maxWait,与通用连接池概念一致。 - 有效性检测:
testWhileIdle、testOnBorrow、testOnReturn、validationQuery。推荐开启testWhileIdle,避免每次借出都检测带来的开销。 - 连接回收与驱逐:
timeBetweenEvictionRunsMillis(驱逐检测线程间隔)、minEvictableIdleTimeMillis(空闲连接最少存活时间)、keepAlive(是否对空闲连接执行 keepAlive 探测)。 - 监控与统计:
filters通常配置stat,wall,slf4j,分别启用监控统计、SQL 防火墙和日志输出。
2. 整合 Spring Boot 的配置示例
首先引入 Druid 的 Spring Boot Starter:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.20</version>
</dependency>
然后在配置文件中设置:
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: app
password: secret
initial-size: 5
min-idle: 10
max-active: 20
max-wait: 5000
test-while-idle: true
test-on-borrow: false
test-on-return: false
validation-query: SELECT 1
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
keep-alive: true
# 监控配置
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-username: admin
login-password: druid123
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,/druid/*'
filter:
stat:
enabled: true
slow-sql-millis: 1000 # 慢SQL阈值(毫秒)
log-slow-sql: true
wall:
enabled: true
config:
select-into-outfile-allow: false
truncate-allow: false
3. 监控与诊断
启动应用后访问 /druid 即可进入监控页面,直观查看:
- 数据源信息:连接池的活跃连接数、峰值、等待线程数等。
- SQL 监控:每条 SQL 的执行次数、平均耗时、最慢耗时、错误次数等。
- SQL 防火墙:拦截的非法 SQL 和黑名单命中情况。
- URI 监控:不同接口对应的 SQL 调用情况,追溯哪个接口拖慢了数据库。
这些信息对于排查生产问题、发现 N+1 查询、识别缓慢接口非常有价值,是 HikariCP 无法直接提供的能力。
13.1.3 连接池的通用性能优化指南
无论选择 HikariCP 还是 Druid,以下几个原则都是共通的:
1. 合理设置连接数,而非盲目调大
连接池大小有一个经典公式:
*连接数 = ((核心数 2) + 有效磁盘数)**
这更多是一个经验起点。实际调优中,应当通过压力测试找到吞吐量的拐点:在不断增加连接数的过程中,吞吐量增长速度变缓甚至下降时,说明已接近数据库处理能力的上限,此时的连接数即为最优。
2. 避免连接超时时间与调用超时的相互干扰
当服务调用方(如网关)的超时时间小于数据库连接池的 max-wait 时,调用方会先断开,连接池却仍在等待连接,造成资源浪费。应确保:
数据库连接池 maxWait < 调用链路的超时时间
3. 开启预编译缓存与优化 SQL
在 MySQL 连接 URL 中添加 useServerPrepStmts=true&cachePrepStmts=true,可利用服务端预编译,减少 SQL 解析开销。同时Druid 的 filter.stat 还能统计 Execute、Prepare的次数,方便判断缓存是否生效。
4. 主动探测空闲连接,防止“僵尸连接”
数据库如遇异常重启或网络闪断,连接池中缓存的连接可能已不可用。testWhileIdle(Druid)和 max-lifetime(HikariCP)的组合,能够确保定时剔除无效连接,保持池内都是可用连接。
5. 泄漏检测
HikariCP 的 leak-detection-threshold 和 Druid 的 removeAbandoned(开启后对遗弃连接进行强制回收)都可以在开发阶段或低风险环境启用,帮助发现未关闭 Connection 的代码 Bug。
13.1.4 选择 HikariCP 还是 Druid?
这并非二选一的零和问题,取决于项目的侧重:
- 追求极致性能、轻量部署:选择 HikariCP。它是 Spring Boot 默认选项,零额外依赖,运行开销极低。
- 需要 SQL 监控、运维可视化、SQL 防火墙:选用 Druid。它在大型团队、复杂业务系统中能够快速定位数据库层问题,降低运维成本。
- 完全可以共存:某些项目中,核心业务库使用 Druid(监控更重要),而日志、消息等辅助库使用 HikariCP,两者在同一个应用中并不冲突。
连接池配置从来不是一劳永逸的,它应随着业务增长、数据库变更和架构演进不断优化。理解参数背后的行为,建立监控与压测反馈闭环,才能真正发挥连接池的威力。