一、SpringBoot连接池全景透视:从选型到实战
SpringBoot可选的连接池多达六款,但真正在生产环境中高频使用的其实只有两款。为清晰呈现全貌,我将它们分为三个梯队:
1、第一梯队:生产环境绝对主力(覆盖95%场景)
- HikariCP:是SpringBoot 2.X/3.X 官方默认。SpringBoot只要引入JDBC Starter就自动拥有,不需要配置它就已经在工作,除非我们明确把它排除,否则他就是我们的连接池。
- Druid:它不是SpringBoot自带的,但在中国开发者生态中是事实上的标配,是国内最流行的第三方替代。当我们需要"看报表、抓慢SQL、防注入"时,它是唯一解。
2、第二梯队:备胎与历史包袱
- Tomcat JDBC Pool:SpringBoot 1.X官方默认,Spring Boot 2.0后被Hikari取代,但自动配置的备胎顺序第二。如果你强制排除了HikariCP,且项目部署在Tomcat环境,它会顶上。
- Common DBCP2:Apache老牌连接池,备胎顺序第三,性能明显落后。目前出现在2018年以前的遗留项目,新项目极不推荐,学了主要用于看懂古董代码。
看到一个项目的连接池配置是spring.datasource.maxActive、maxIdle这种命名风格的,99%是DBCP或Tomcat JDBC(Druid/Hikari不用这套命名)。
3、第三梯队:特殊场景/边缘选项
- Oracle UCP:企业版Oracle数据库强制捆绑,Spring Boot自动配置也支持它(备胎顺序第四)。
- c3p0 / proxool:SSH/Struts时代的遗老,Spring Boot官方从未默认集成过。
对于学习数据库连接池,80%精力放在HikariCP和Druid上就已足够,其他连接池遇到能认出来即可。
下面我们来详细对HikariCP和Druid进行深度学习。
二、HikariCP vs Druid:核心能力全景对比
| 维度 | HikariCP(SpringBoot默认) | Druid(阿里开源) |
|---|---|---|
| 设计哲学 | 极简主义,只做连接管理 | 大而全,连接池+监控+安全三合一 |
| 性能标杆 | 业界最快,延迟极低 | 高性能,监控开销可控 |
| 监控能力 | 基础:JMX/Micrometer指标导出 | 王者级:内置Web监控、SQL分析、防SQL注入防火墙 |
| 连接泄漏诊断 | leakDetectionThreshold超时未归还则报警 |
removeAbandoned自动回收泄漏连接+堆栈跟踪 |
| SpringBoot集成 | 自动默认,零配置即用 | 需引入专用Starter并排除默认 |
| SQL防火墙 | 无 | WallFilter,拦截高危SQL |
| 慢SQL排行榜 | 无 | 内置,支持阈值设置 |
| 典型场景 | 通用业务系统、高并发低延迟交易、微服务 | 需可视化运维、SQL审计、安全防护的大型系统 |
三、实战配置
1. HikariCP:SpringBoot的"御林军"
HikariCP的极致性能源于字节码级别的优化,源码中有三大经典设计:
-
FastList:替换JDK的
ArrayList,移除了边界校验,在getConnection()循环中效率更高 。 -
ConcurrentBag:放弃传统的
BlockingQueue,采用无锁设计 + ThreadLocal缓存。一个线程归还的连接,优先被同一个线程再次借出,大幅减少竞争 。 -
不做的哲学:它不提供内置的Web监控,正是因为坚持"连接池只做连接管理",绝不引入无关逻辑影响核心路径。
(1)依赖配置
使用时通过JDBC Starter间接引入,无需显示导入。
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
(2)yml完整配置示例
XML
spring:
datasource:
url: jdbc:mysql://localhost:3306/springboot_demo?useSSL=false&serverTimezone=UTC
username: root
password: 2020
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource # 显式指定(可省略,默认就是Hikari)
# HikariCP专属配置(全部在hikari节点下)
hikari:
# 核心参数
maximum-pool-size: 10 # 最大连接数,默认10
minimum-idle: 10 # 最小空闲连接,默认10(建议等于maximum-pool-size)
connection-timeout: 30000 # 等待连接的超时时间(毫秒),默认30000
idle-timeout: 600000 # 连接最大空闲时间(毫秒),默认600000(10分钟)
max-lifetime: 1800000 # 连接最大生命周期(毫秒),默认1800000(30分钟)
# 性能调优参数
keepalive-time: 0 # 保持活跃时间(毫秒),0表示禁用,建议60000
validation-timeout: 5000 # 连接测试超时,默认5000
leak-detection-threshold: 3000 # 连接泄漏检测阈值,0表示禁用,开发环境建议3000
# 连接测试
connection-test-query: SELECT 1 # 测试SQL,MySQL可用,H2/PostgreSQL无需设置
# 连接池名称(便于监控识别)
pool-name: MyHikariPool
# 是否自动提交事务
auto-commit: true
2. Druid:自带"仪表盘"的运维利器
它的核心价值不是连接,是数据 。
Druid的强大在于它将连接池、监控、安全三合一 。生产环境中,运维人员可以直接访问/druid/index.html看到:
- SQL防火墙(WallFilter):拦截
delete from user这种无where条件的高危语句 。 - 慢SQL排行榜:精确统计每个SQL的执行次数、耗时、并发数 。
- 连接泄漏现场:当
removeAbandoned=true时,不仅能回收泄漏连接,还能打印出该连接是从哪行代码获取的堆栈信息 。
Druid有两种用法:
| 维度 | 用法一:自定义注册类 | 用法二:Starter自动配置 |
|---|---|---|
| 依赖 | druid 核心包 |
druid-spring-boot-starter |
| 配置方式 | YAML平铺 + @ConfigurationProperties |
YAML分层(druid节点下)+ 零代码 |
| IDEA提示 | cannot resolve(无白名单) |
完美提示(有白名单) |
| 代码量 | 20-30行Java配置 | 0行Java配置 |
| 原理 | 手动创建DataSource并绑定属性 | Spring Boot自动装配 + 约定大于配置 |
(1)依赖配置
使用时需显示引入Starter,并排除默认HikariCP
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.20</version>
</dependency>
(2)yml完整配置示例
XML
spring:
datasource:
url: jdbc:mysql://localhost:3306/springboot_demo?useSSL=false&serverTimezone=UTC
username: root
password: 2020
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource # 显式指定Druid
# Druid连接池配置(直接配置在datasource下,不需要druid节点)
# 基本参数
initial-size: 5 # 初始化连接数
min-idle: 5 # 最小空闲连接
max-active: 20 # 最大活跃连接数
max-wait: 60000 # 获取连接等待超时时间(毫秒)
# 性能与测试
time-between-eviction-runs-millis: 60000 # 空闲连接检测周期
min-evictable-idle-time-millis: 300000 # 连接最小空闲时间
validation-query: SELECT 1 # 验证SQL
test-while-idle: true # 空闲时测试
test-on-borrow: false # 获取时测试(不建议开启,影响性能)
test-on-return: false # 归还时测试(不建议开启)
# Druid专属功能
# 1. 连接泄漏回收
remove-abandoned: true # 是否自动回收泄漏连接
remove-abandoned-timeout: 1800 # 泄漏连接超时时间(秒)
log-abandoned: true # 关闭泄漏连接时是否记录日志
# 2. 监控统计
filters: stat,wall,log4j2 # 开启统计、防火墙、日志
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=2000 # 慢SQL阈值
# 3. Web监控(单独节点)
druid:
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-username: admin
login-password: admin
allow: 127.0.0.1
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: /druid/*,*.js,*.css,*.gif,*.jpg,*.png
(3)创建数据源注册类
java
/**
* 创建数据源注册类
*/
@Configuration
public class DruidConfig {
/**
* 创建数据源并绑定所有spring.datasource下的属性
*
* 监听:告诉Spring"我要监听所有以spring.datasource开头的配置"
* 匹配:Spring启动时会扫描YAML/Properties文件,提取spring.datasource.xxx的所有属性
* 注入:通过Setter方法将属性值注入到DruidDataSource对象中
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource(){
return new DruidDataSource();
}
// 手动配置监控台
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),
"/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","root");
initParams.put("loginPassword","root");
initParams.put("allow","");//默认就是允许所有访问
initParams.put("deny","192.168.15.21");
bean.setInitParameters(initParams);
return bean;
}
// 配置一个web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean;
bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
创建配置源注册类之后,yml的Druid参数属性会被@ConfigutationProperties绑定到DruidDataSource,即使yml配置的Druid参数显示cannot resolve也没关系,这只是因为通过@ConfigutationProperties绑定的属性,没有在任何JSON文件中注册,所以IDEA不认识------但它完全能工作,因为运行时Spring会处理。
如果我们想要通过Starter自动配置来使用Druid,只需要导入druid-spring-boot-starter依赖,在yml配置文件中按照提示配置需要的参数即可。
四、常用连接池参数详解(按优先级分类)
1、必知必会参数
| 参数 | HikariCP | Druid | 含义与建议 |
|---|---|---|---|
| 最大连接数 | maximum-pool-size |
max-active |
最重要的参数 。不是越大越好!通常10-20足够,高并发可到50-100。计算公式:(核心线程数*2) + (有效存储设备数) |
| 最小空闲连接 | minimum-idle |
min-idle |
建议=最大连接数。避免频繁创建/销毁连接,Hikari官方推荐这样设置 |
| 获取连接超时 | connection-timeout |
max-wait |
业务线程等待连接的最大时间。必须设置,默认30秒。建议30000(30秒) |
| 连接最大生命周期 | max-lifetime |
无直接对应 | 必须小于数据库的wait_timeout(MySQL默认28800秒)。建议1800000(30分钟) |
| 空闲连接存活时间 | idle-timeout |
min-evictable-idle-time-millis |
连接空闲多久后被回收。Hikari默认为10分钟,仅当minimum-idle < maximum-pool-size时生效 |
2、进阶参数(性能调优)
| 参数 | HikariCP | Druid | 含义与建议 |
|---|---|---|---|
| 连接测试SQL | connection-test-query |
validation-query |
MySQL需要手动设置 为SELECT 1。H2/PostgreSQL等无需设置,驱动自带快速校验 |
| 空闲连接检测 | 无直接对应 | test-while-idle + time-between-eviction-runs-millis |
后台线程定期检测空闲连接是否可用。建议开启 |
| 连接泄漏检测 | leak-detection-threshold |
remove-abandoned-timeout |
开发环境必开! Hikari仅告警不回收,Druid/DBCP2可自动回收 |
| PreparedStatement缓存 | 内置支持(无法关闭) | pool-prepared-statements |
缓存预编译SQL,提升性能。Druid默认关闭,建议开启 |
3、Druid独有参数(监控/安全)
| 参数 | 含义 | 建议 |
|---|---|---|
filters |
配置监控统计过滤器 | 至少开启stat(统计)和wall(防火墙) |
druid.stat.slowSqlMillis |
慢SQL阈值 | 设置2000(2秒) |
remove-abandoned |
自动回收泄漏连接 | 生产环境谨慎!可能误回收长事务 |
druid.stat-view-servlet |
监控页面配置 | 生产环境务必设置allow和密码 |
五、如何选型?
HikariCP是性能标杆, Druid是运维平台。HikariCP无脑默认,90%场景适用。当老板要看SQL监控报表、需要SQL防火墙、必须可视化运维时,选择Druid。
先让连接池跑起来,再用监控发现问题,最后针对性调参。不要上来就复制网上一堆优化参数。