☰
Druid 连接池调优实战:连接获取丝滑到毫秒级
2026/10/29 19:29:02 网站建设 项目流程

Druid 连接池调优实战:连接获取丝滑到毫秒级

【免费下载链接】druid阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池项目地址: https://gitcode.com/gh_mirrors/druid/druid

高并发下页面一卡,慢的到底是 SQL,还是getConnection()前面的等待?Druid 是一个为监控而生的数据库连接池:DruidDataSource不仅管住连接的借还,还能告诉你哪条 SQL 慢、哪个连接被泄漏了。

它到底在解决什么

Druid 是一个 Java 数据库连接池,核心实现是DruidDataSource。它干三件事:管理物理连接的完整生命周期(预创建、借用、归还、驱逐);内置 Filter 链采集 SQL 执行统计、慢 SQL 与 Web 请求数据;把这些全部暴露到 JMX 和内置 Web 监控页。有了它,数据库层从黑盒变成一块仪表盘。

核心机制拆解

机制一:连接获取——定长数组 + 等待唤醒

一句话:连接放在定长数组里,poolingCount是空闲边界,空了就把线程挂进等待队列,靠"连接归还"信号唤醒,不空转。

while (poolingCount == 0) { emptySignal(); // 通知后台创建新连接 notEmpty.await(estimate, MILLISECONDS); // 等归还信号,maxWait 兜底 } holder = connections[poolingCount]; // 取走空闲位并转为活跃

为什么这样设计:ReentrantLock+Condition替代轮询,归还端与创建端互相signal,正常负载下getConnection()一次都不空转;超时任用maxWait控制,超时异常里直接带着 active / maxActive 现场信息。

机制二:SQL 统计——无锁累加 + 直方图

一句话:每次执行都进JdbcSqlStat.addExecuteTime,用 CAS 累加总耗时,并落进 0-1ms / 1-10ms / … / 1s+ 的直方图。

public void addExecuteTime(long nanoSpan) { executeSpanNanoTotalUpdater.addAndGet(this, nanoSpan); // 无锁累加 histogramRecord(nanoSpan); // 按桶计数 }

为什么这样设计:统计走AtomicLongFieldUpdater,高 QPS 下不抢锁;存直方图桶而非每次采样值,内存恒定。监控页上的"请求时间(最慢)""总时间"两列,就是这两个字段的换算结果。

从零到跑通

1. 加依赖

Spring Boot 项目引入一个 starter 即可,Boot 3 以上换druid-spring-boot-3-starter:

<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.17</version> </dependency>

2. 配置数据源与监控

spring.datasource.url / username / password照旧填,再叠加 druid 参数:

spring: datasource: druid: initial-size: 5 # 初始连接数 max-active: 20 # 最大连接数 max-wait: 60000 # 获取超时(ms),避免无限等待 validation-query: SELECT 1 test-while-idle: true # 空闲检测,推荐开启 filters: stat,wall # stat 统计,wall SQL 防火墙 stat-view-servlet: enabled: true login-username: admin login-password: your_password

3. 启动验证

java -jar app.jar # 浏览器打开 http://127.0.0.1:8080/druid/index.html

用账号密码登录后,首页 Stat Index 能看到数据源的ActiveCount(使用中)、PoolingCount(空闲)、WaitThreadCount(等待获取的线程);"Web应用"菜单下每个 URI 的请求次数与时间分布一目了然,慢请求不用猜。

踩坑与调优

坑一:获取超时 GetConnectionTimeoutException

症状:高峰期借连接超时,异常信息形如wait millis xxx, active 20, maxActive 20。根因:多数是连接泄漏或慢 SQL 长时间占用。修复:开发环境开泄漏检测,打印借出堆栈定位,生产别开:

ds.setRemoveAbandoned(true); // 回收未归还的连接 ds.setRemoveAbandonedTimeout(300); // 回收阈值(秒) ds.setLogAbandoned(true); // 泄漏时打印借用堆栈

坑二:借到死连接 Communications link failure

症状:偶发Communications link failure或 connection reset。根因:MySQLwait_timeout早已掐断空闲连接,池里没察觉。修复:空闲检测 + 保活,别用testOnBorrow,它每次借都跑一次检测 SQL:

spring: datasource: druid: test-while-idle: true keep-alive: true

坑三:慢 SQL 只有数字没有参数

症状:监控页看到某条 SQLMaxTimespan秒级,却说不清是哪些参数慢。根因:慢 SQL 日志默认关闭,且阈值默认 3 秒。修复:调低阈值并打开日志:

spring: datasource: druid: filter: stat: slow-sql-millis: 500 log-slow-sql: true

怎么配 / 怎么选

连接池参数调优里变化最大的变量是检测策略,先看 QPS 再选:

策略触发时机性能开销适用场景
testOnBorrow每次借出每次都执行检测 SQL,最大低 QPS 高可靠事务链路
testWhileIdle借出时若空闲超阈值只检测空闲连接,小多数生产环境
keepAlive定时对空闲连接发心跳最小连接常空闲、DB 侧会主动断开
推荐组合testWhileIdle+keepAlive+maxWait=60s最小生产默认,必须配validationQuery

另一个容易配错的是 PSCache(预编译语句缓存):MySQL 不建议开,Oracle / PostgreSQL 建议开;调用setMaxPoolPreparedStatementPerConnectionSize(n)(n>0)会自动开启,不用再手动设poolPreparedStatements。

延伸与参考

  • doc/connection-pool-guide.md:容量、检测、回收全参数清单与默认值
  • doc/monitoring-guide.md:监控页面、JSON API 与 Prometheus 对接
  • doc/wall-security-guide.md:Wall 防火墙配置,拦截危险 SQL 与注入
  • druid-demo-petclinic/:Spring Boot 集成 Druid 的可运行示例
  • core/src/main/java/com/alibaba/druid/pool/DruidDataSource.java:核心源码,借还、驱逐、检测都在这里

【免费下载链接】druid阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池项目地址: https://gitcode.com/gh_mirrors/druid/druid

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询