2. Druid核心架构:连接池的内部组件与工作流程

要真正掌握Druid连接池的调优,不能只停留在参数配置层面,必须深入理解其内部架构。Druid之所以在阿里巴巴内部及众多高并发支付系统中被广泛采用,核心在于其精巧的组件化设计与可插拔的过滤器链机制。本章将拆解Druid的三大核心组件:连接工厂、过滤器链与监控统计,并梳理一条完整的连接生命周期工作流程。

架构视角: Druid的设计遵循“职责分离”原则——连接工厂负责物理连接的创建与销毁,过滤器链负责横切关注点(监控、日志、安全),而连接池本身只管理空闲与活跃连接的状态机。

2.1 核心组件总览

Druid连接池的内部架构可以抽象为以下四个核心模块,它们协同工作,支撑起高性能、可监控的连接管理能力。

组件 职责 关键实现类
连接池管理器 维护连接状态(空闲/活跃)、执行获取/回收/销毁策略、支持连接泄漏检测 DruidDataSource
连接工厂 封装物理连接的创建(Driver.getConnection())与销毁(Connection.close()),支持连接属性注入 DruidAbstractDataSource.DruidConnectionFactory
过滤器链 以责任链模式拦截连接操作,实现监控统计、日志、安全过滤、慢SQL检测等扩展功能 FilterChainImpl + 各 Filter 实现
监控统计模块 采集连接池状态、SQL执行耗时、并发数等指标,通过JMX或HTTP API暴露 DruidStatManagerFacade、StatFilter
Druid连接池核心组件架构 Druid连接池核心组件架构 DruidDataSource 连接池管理器(状态机 + 策略) 连接工厂 物理连接创建/销毁 属性注入、预编译缓存 过滤器链 责任链模式拦截操作 监控/日志/安全/慢SQL 监控统计模块 JMX / HTTP API / 日志 创建/销毁 拦截/增强 采集指标 状态上报

2.2 连接工厂:物理连接的封装者

连接工厂是Druid与底层JDBC驱动之间的桥梁。它负责将DriverManager.getConnection()返回的原生连接包装成Druid的内部连接对象(DruidPooledConnection),并在此过程中注入连接属性、设置超时、初始化预编译缓存。

关键设计点:
  • 延迟初始化: 连接工厂在首次获取连接时才真正创建物理连接,避免启动时加载过多连接。
  • 连接属性注入: 通过connectProperties配置,可设置useServerPrepStmts、cachePrepStmts等MySQL优化参数。
  • 异常重试: 当创建连接失败时,Druid支持可配置的重试次数(connectionErrorRetryAttempts),避免瞬态故障导致连接池枯竭。

2.3 过滤器链:可插拔的拦截器体系

过滤器链是Druid最具扩展性的设计。它基于责任链模式,允许在连接获取、执行SQL、事务提交/回滚等关键操作前后插入自定义逻辑。每个过滤器实现Filter接口,通过filters配置按序加载。

支付系统中常用的内置过滤器包括:

过滤器名称 别名 核心功能 支付场景价值
StatFilter stat 统计SQL执行耗时、并发数、结果集大小 识别慢查询,定位支付链路瓶颈
WallFilter wall SQL注入防火墙,拦截危险SQL 防止支付接口被恶意SQL注入
LogFilter log4j/slf4j 记录SQL执行日志(可配置慢SQL阈值) 审计与问题追踪
EncodingFilter encoding 自动设置客户端字符编码 避免中文乱码导致支付失败

过滤器链的执行顺序由filters配置中的逗号分隔顺序决定。例如:filters: stat,wall,slf4j 表示先执行统计,再执行安全拦截,最后记录日志。

2.4 监控统计模块:可观测性的基石

监控统计模块是Druid区别于其他连接池(如HikariCP)的核心竞争力。它通过StatFilter采集数据,并聚合到DruidStatManagerFacade中,支持以下维度的实时监控:

  • 连接池维度: 当前活跃连接数、空闲连接数、等待获取连接的线程数、连接创建/销毁速率。
  • SQL维度: 执行次数、总耗时、最大耗时、并发执行数、慢SQL列表(可配置慢SQL阈值slowSqlMillis)。
  • 事务维度: 事务提交/回滚次数、事务平均耗时、活跃事务数。
生产环境注意: 监控统计会带来一定的性能开销(约5%~10%的额外CPU消耗)。在支付核心链路上,建议仅在调试或巡检时开启StatFilter,日常生产环境可关闭或仅开启关键指标采集。

2.5 完整工作流程:一次连接获取的生命周期

下面通过一次典型的getConnection()调用,串联起所有核心组件的工作流程。

  1. 调用入口: 业务代码调用 dataSource.getConnection()。
  2. 连接池管理器判断: DruidDataSource 检查当前空闲连接队列是否为空。
    • 若空闲队列非空,直接取出一个DruidPooledConnection,进入步骤4。
    • 若空闲队列为空,检查当前活跃连接数是否达到maxActive上限。
  3. 创建物理连接: 若未达上限,调用连接工厂创建新的物理连接,包装为DruidPooledConnection。
  4. 过滤器链拦截: 在返回连接前,过滤器链依次执行:
    • StatFilter 记录连接获取耗时。
    • WallFilter 检查连接来源是否安全。
    • LogFilter 输出连接获取日志。
  5. 监控统计上报: 连接获取成功后,监控统计模块更新活跃连接数、等待时间等指标。
  6. 返回连接: 业务代码获得DruidPooledConnection,执行SQL操作。
  7. 连接回收: 业务调用connection.close()时,连接池管理器将连接归还至空闲队列,并触发过滤器链的回收后处理(如统计连接使用时长)。
Druid连接获取完整工作流程 连接获取完整工作流程 ① 业务调用 getConnection() ② 检查空闲队列 空闲非空 空闲为空 ③a 取出空闲连接 ③b 连接工厂创建 ④ 过滤器链拦截 Stat → Wall → Log ⑤ 监控统计上报 ⑥ 返回 DruidPooledConnection

2.6 组件协作总结