连接池配置

数据库连接的创建开销高(TCP 握手 + 认证),连接池通过预创建并复用连接大幅降低延迟。Spring Boot 默认集成 HikariCP,国内项目也广泛使用阿里的 Druid

HikariCP(默认)

引入任何 spring-boot-starter-data-* 依赖时,HikariCP 自动成为连接池实现。

基础配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
    username: root
    password: secret
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      # 连接池大小
      minimum-idle: 5           # 空闲时维持的最小连接数
      maximum-pool-size: 20     # 最大连接数(核心参数)
      # 超时配置
      connection-timeout: 30000     # 获取连接的最长等待时间(ms),超时抛异常
      idle-timeout: 600000          # 空闲连接被回收的时间(ms)
      max-lifetime: 1800000         # 连接最大存活时间(ms),需 < 数据库 wait_timeout
      # 连接检测
      connection-test-query: SELECT 1   # MySQL 可省略,HikariCP 有更高效的内部检测
      keepalive-time: 120000        # 定期保活(防止防火墙断开空闲连接)
      pool-name: HikariPool-Main

连接池大小公式

经验公式(OLTP 场景):

最佳连接数 ≈ 核心线程数 × 2 + 有效磁盘数

HikariCP 官方建议:连接数越少越好,过多连接会加剧数据库竞争。实际调优以监控数据为准,而非拍脑袋。

场景推荐 maximum-pool-size
单实例 8 核,纯 OLTP20~40
8 核,含大量慢查询10~20
多实例部署(每实例)总连接数 / 实例数

max-lifetime 说明

数据库服务端通常有连接超时(MySQL 默认 wait_timeout=28800s,即 8 小时)。max-lifetime 必须小于数据库的超时时间,否则 HikariCP 持有的连接已被服务端关闭,使用时会报 Connection is closed

hikari:
  max-lifetime: 1800000   # 30 分钟,远小于 MySQL 8 小时超时

Druid

Druid 是阿里开源的连接池,内置 SQL 监控、慢查询日志、数据库密码加密等功能。

引入依赖

implementation 'com.alibaba:druid-spring-boot-3-starter:1.2.22'

配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 连接池大小
      initial-size: 5
      min-idle: 5
      max-active: 20
      # 超时
      max-wait: 60000           # 获取连接最大等待时间(ms)
      min-evictable-idle-time-millis: 300000
      max-evictable-idle-time-millis: 900000
      # 连接检测
      test-while-idle: true     # 从池中取连接时检测
      test-on-borrow: false     # 借出时检测(影响性能,一般关闭)
      test-on-return: false
      validation-query: SELECT 1
      keep-alive: true
      # SQL 监控(Druid 特色)
      filter:
        stat:
          enabled: true
          log-slow-sql: true
          slow-sql-millis: 1000     # 超过 1s 记录为慢 SQL
          merge-sql: true
        wall:
          enabled: true             # SQL 防火墙,防注入
      # 监控控制台
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: admin
        login-password: admin123
        allow: 127.0.0.1           # 只允许本地访问
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: "*.js,*.gif,*.jpg,*.css,/druid/*"

访问 http://localhost:8080/druid 查看监控面板(SQL 统计、慢查询、连接池状态)。

生产环境建议关闭或限制 stat-view-servlet,防止内部监控数据暴露。

数据库密码加密

# 生成加密密钥和密文
java -cp druid-1.2.x.jar com.alibaba.druid.filter.config.ConfigTools yourPassword
# 输出:privateKey / publicKey / password(密文)
spring:
  datasource:
    druid:
      password: <加密后的密文>
      filter:
        config:
          enabled: true
      connection-properties: config.decrypt=true;config.decrypt.key=<publicKey>

多数据源连接池

多数据源场景下每个 DataSource 独立配置连接池:

@Configuration
public class DataSourceConfig {
 
    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.primary.hikari")
    public DataSource primaryDataSource(
        @Value("${spring.datasource.primary.url}") String url,
        @Value("${spring.datasource.primary.username}") String username,
        @Value("${spring.datasource.primary.password}") String password
    ) {
        return DataSourceBuilder.create()
            .url(url).username(username).password(password)
            .build();
    }
 
    @Bean
    @ConfigurationProperties("spring.datasource.secondary.hikari")
    public DataSource secondaryDataSource(...) { ... }
}
spring:
  datasource:
    primary:
      url: jdbc:mysql://primary-host:3306/main
      hikari:
        maximum-pool-size: 20
        pool-name: HikariPool-Primary
    secondary:
      url: jdbc:mysql://secondary-host:3306/analytics
      hikari:
        maximum-pool-size: 10
        pool-name: HikariPool-Secondary

多数据源详见 多数据源


连接池监控(Actuator)

management:
  endpoints:
    web:
      exposure:
        include: health, metrics
  endpoint:
    health:
      show-details: always

HikariCP 自动暴露指标,可通过 Actuator 查看:

GET /actuator/metrics/hikaricp.connections.active    # 活跃连接数
GET /actuator/metrics/hikaricp.connections.idle      # 空闲连接数
GET /actuator/metrics/hikaricp.connections.pending   # 等待获取连接的线程数
GET /actuator/metrics/hikaricp.connections.acquire   # 获取连接的平均耗时

应用监控详见 Actuator监控


HikariCP vs Druid 对比

对比项HikariCPDruid
性能极高(业界最快)略低,但差距不大
监控依赖 Micrometer / Actuator内置 Web 控制台,开箱即看
SQL 拦截内置统计、慢查询、防注入
密码加密不内置内置 ConfigFilter
配置复杂度
适用场景对性能敏感,有独立监控体系需要 SQL 审计、内置监控的项目

选型建议:

  • 新项目 + 有 Prometheus/Grafana:HikariCP(默认,省心)
  • 需要 SQL 审计 / 慢查询分析 / 简单内置监控:Druid

常见问题

连接池耗尽(Connection timeout)

HikariPool - Connection is not available, request timed out after 30000ms

排查方向:

  1. maximum-pool-size 设置过小
  2. 存在连接泄漏:事务未提交/回滚,连接未释放
  3. 慢查询导致连接长时间占用

定位连接泄漏:

hikari:
  leak-detection-threshold: 5000   # 连接被借出超过 5 秒打警告日志

8 小时断连(CommunicationsException)

MySQL wait_timeout 默认 8 小时,长时间无请求后连接被服务端关闭:

hikari:
  max-lifetime: 1800000       # 30 分钟,强制主动替换连接
  keepalive-time: 120000      # 每 2 分钟发一次 keepalive 包
  connection-test-query: SELECT 1

读写分离场景

连接池配合读写分离路由时,主库写连接和从库读连接应使用独立的连接池,详见 读写分离


相关链接