Druid 使用全面详解

阿里巴巴 Druid 是目前 Java 生态中最强大的数据库连接池,集连接池、监控、安全防护于一体。本文将全面介绍 Druid 的核心功能、配置详解、高级特性和最佳实践。

一、Druid 核心优势

  1. 性能卓越:经过阿里巴巴双十一大促验证

  2. 全面监控:内置强大的 SQL 监控平台

  3. 安全防护:提供 SQL 防火墙和攻击防护

  4. 扩展性强:支持 Filter 链扩展机制

  5. 功能丰富:支持密码加密、多数据源等企业级功能

二、快速集成(Maven)

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

三、基础配置(application.yml)

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/prod_db?useSSL=false&serverTimezone=UTC
    username: admin
    password: securePass123!
    driver-class-name: com.mysql.cj.jdbc.Driver
    
    # 数据源类型配置
    type: com.alibaba.druid.pool.DruidDataSource
    
    druid:
      # 连接池基础配置
      initial-size: 5
      min-idle: 5
      max-active: 50
      max-wait: 3000  # 获取连接超时时间(毫秒)
      
      # 连接检测配置
      validation-query: SELECT 1
      test-while-idle: true    # 建议启用
      test-on-borrow: false    # 获取连接时不检查(高并发影响性能)
      test-on-return: false    # 归还连接时不检查
      time-between-eviction-runs-millis: 60000  # 检测间隔(毫秒)
      min-evictable-idle-time-millis: 300000    # 最小空闲时间(毫秒)
      max-evictable-idle-time-millis: 600000    # 最大空闲时间(毫秒)
      
      # 监控管理配置
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: admin    # 监控平台用户名
        login-password: druid123 # 监控平台密码
        reset-enable: false      # 禁用重置功能
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
      filter:
        stat:
          enabled: true
          log-slow-sql: true     # 启用慢SQL记录
          slow-sql-millis: 2000  # 慢SQL判定阈值(毫秒)
          merge-sql: true        # 合并相似SQL
        wall:
          enabled: true          # 启用SQL防火墙
          config:
            drop-table-allow: false # 禁止删除表操作
 

四、核心参数详解

参数 默认值 说明 生产建议
initial-size 0 初始化连接数 5-10
min-idle 0 最小空闲连接数 与 initial-size 相同
max-active 8 最大连接数 根据DB性能设置(20-100)
max-wait -1 获取连接超时时间(ms) 必须设置(2000-5000)
validation-query - 连接检查SQL SELECT 1
test-while-idle true 空闲时检查连接 推荐开启
time-between-eviction-runs-millis 60000 空闲检查间隔(ms) 60000(1分钟)
min-evictable-idle-time-millis 1800000 最小空闲时间(ms) 300000(5分钟)
max-evictable-idle-time-millis 25200000 最大空闲时间(ms) 600000(10分钟)

重要提示max-wait 必须设置为正值,避免线程无限阻塞

五、监控中心使用

访问地址:http://localhost:8080/druid/index.html

核心功能模块:

  1. 数据源:连接池实时状态(活跃连接、等待线程)

  2. SQL监控

    • SQL执行统计(执行次数、最慢、平均耗时)

    • 慢SQL识别(超过阈值自动标记)

    • SQL执行时间分布

  3. SQL防火墙

    • 拦截的SQL攻击统计

    • 黑白名单管理

  4. Web应用

    • URI请求统计

    • Session监控

  5. 连接泄露检测

    • 未关闭连接追踪

    • 泄露连接堆栈信息

六、Filter 配置详解

Druid 通过 Filter 链实现功能扩展:

常用内置 Filter:

  1. stat:SQL 统计监控

  2. wall:SQL 防火墙

  3. log4j/logback:日志记录

  4. config:密码解密

  5. encoding:字符编码转换

自定义 Filter 配置:

@Bean
public FilterRegistrationBean<WebStatFilter> webStatFilter() {
    FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>();
    bean.setFilter(new WebStatFilter());
    bean.addUrlPatterns("/*");
    bean.addInitParameter("exclusions", "*.js,*.css,/druid/*");
    return bean;
}

@Bean
public FilterRegistrationBean<StatFilter> statFilter() {
    FilterRegistrationBean<StatFilter> bean = new FilterRegistrationBean<>();
    bean.setFilter(new StatFilter());
    bean.addInitParameter("slowSqlMillis", "2000");  // 设置慢SQL阈值
    bean.addInitParameter("logSlowSql", "true");     // 开启慢SQL记录
    bean.addInitParameter("mergeSql", "true");       // 启用SQL合并功能
    return bean;
}
 

七、SQL 防火墙(WallFilter)

防护策略:

  1. 禁止 DELETE 不带 WHERE 条件

  2. 禁止 DROP/TRUNCATE 表

  3. 禁止 SELECT *(可配置)

  4. 检测永真条件(如 WHERE 1=1

  5. 防御 SQL 注入攻击

配置示例:

spring:
  datasource:
    druid:
      filter:
        wall:
          enabled: true
          config:
            delete-allow: false       # 禁用删除操作
            drop-table-allow: false    # 禁用删除表操作  
            select-all-column-allow: false # 禁用SELECT *查询
            condition-and-always-true-allow: false # 禁用永真条件
            condition-and-always-false-allow: false # 禁用永假条件
 

八、数据库密码加密

步骤1:生成加密密码

# 使用Druid工具加密密码
java -cp druid-1.2.20.jar com.alibaba.druid.filter.config.ConfigTools your_password
 

输出结果:

私钥: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA0dX4CaL...
公钥: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANHV+Am...
密码: ZP3SZHN0UQKZ...
 

步骤2:配置加密密码

spring:
  datasource:
    password: {encrypted_string}
    druid:
      filter:
        config:
          enabled: true
      connect-properties:
        config.decrypt: true
        config.decrypt.key: {public_key}
 

九、多数据源配置

@Configuration
public class DruidConfig {
    
    @Bean
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    public DataSource slaveDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DataSource dynamicDataSource(
            @Qualifier("masterDataSource") DataSource masterDataSource,
            @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        DynamicDataSource dataSource = new DynamicDataSource();
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("master", masterDataSource);
        dataSourceMap.put("slave", slaveDataSource);
        dataSource.setTargetDataSources(dataSourceMap);
        dataSource.setDefaultTargetDataSource(masterDataSource); // 默认使用主库
        return dataSource;
    }
}
 

对应 YAML 配置:

spring:
  datasource:
    druid:
      master:
        url: jdbc:mysql://master-host:3306/db
        username: root
        password: master_pass
        max-active: 20
      slave:
        url: jdbc:mysql://slave-host:3306/db
        username: root
        password: slave_pass
        max-active: 20
 

十、最佳实践

  1. 连接池大小

    • 初始值:CPU 核心数 × 2

    • 最大值:根据数据库性能调整(通常 20-100)

    • 公式:max-active = (平均QPS × 平均耗时(ms)) / 1000 + 缓冲

  2. 监控配置

    druid:
      stat-view-servlet:
        enabled: true
        allow: 192.168.1.100,127.0.0.1  # 允许访问的IP
        deny: 192.168.1.73              # 禁止访问的IP
     
    

  3. 慢 SQL 优化

    filter:
      stat:
        slow-sql-millis: 1000  # 慢SQL判定阈值(毫秒)
        log-slow-sql: true     # 是否记录慢SQL日志
     
    

  4. 连接泄露检测

    druid:
      remove-abandoned: true
      remove-abandoned-timeout: 300  # 5分钟超时设置
      log-abandoned: true            # 开启资源回收日志记录
     
    

十一、高级功能

1. 分库分表支持

// 配置Druid分库分表数据源
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDbType("mysql");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:loadbalance://host1,host2,host3/db");

// 设置负载均衡策略
Properties properties = new Properties();
properties.setProperty("loadBalanceStrategy", "random");
dataSource.setConnectProperties(properties);
 

2. 连接持有者跟踪

// 配置连接泄漏检测
druidDataSource.setRemoveAbandoned(true); // 开启连接回收
druidDataSource.setRemoveAbandonedTimeoutMillis(300000); // 设置5分钟超时
druidDataSource.setLogAbandoned(true); // 记录泄漏日志

// 获取连接并设置持有者标识
try (Connection conn = dataSource.getConnection()) {
    DruidPooledConnection druidConn = (DruidPooledConnection) conn;
    druidConn.setConnectionHolder("OrderService.createOrder"); // 标记连接用途
    // 执行业务逻辑...
}
 

3. 自定义监控项

// 注册自定义监控指标
DruidStatManagerFacade.getInstance().registerCustomStat("order_count", 
    new CustomStat() {
        @Override
        public Map<String, Object> getStatData() {
            Map<String, Object> data = new HashMap<>();
            data.put("count", OrderCounter.get());
            return data;
        }
    });
 

十二、常见问题解决方案

  1. 监控页面无法访问

    • 检查 stat-view-servlet.enabled=true

    • 确认 url-pattern 未被安全框架拦截

    • 查看是否配置了 allow/deny IP 限制

  2. 获取连接超时

    • 增大 max-wait 值(优先排查慢 SQL)

    • 检查连接泄露(监控页的"连接泄露"标签)

    • 适当增加 max-active

  3. 慢 SQL 分析

    • 启用 stat 过滤器的 log-slow-sql

    • 使用 Druid 的 SQL 分析工具

    -- 执行计划分析
    EXPLAIN 
    SELECT * 
    FROM large_table 
    WHERE condition;
     
    

  4. SQL 防火墙误拦截

    • 查看拦截日志确定原因

    • 添加白名单:

    wall:
      config:
        allowed_schemas: public, order_db
        allowed_tables: user, order
     
    

十三、性能优化建议

  1. 启用 PSCache

    druid:
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
     
    

  2. 合理配置超时

    druid:
      max-wait: 3000  # 最大等待时间(毫秒)
      query-timeout: 30  # 查询超时时间(秒)
      transaction-query-timeout: 30  # 事务查询超时时间(秒)
     
    

  3. 连接有效性检查优化

    druid:
      validation-query: SELECT 1 FROM DUAL  # 数据库连接验证SQL
      test-while-idle: true                # 空闲时检测连接有效性
      test-on-borrow: false                # 获取连接时不验证
      validation-query-timeout: 1          # 验证查询超时时间(秒)
     
    

十四、Druid vs HikariCP

特性 Druid HikariCP
性能 优秀(接近 HikariCP) 极致
监控功能 内置强大监控平台 需集成第三方监控
SQL防火墙 内置
密码加密 支持 不支持
配置复杂度 较复杂 简单
扩展性 Filter 链机制 有限
多数据源支持 完善 基础
适用场景 企业级应用、需要监控和安全 追求极致性能的微服务

十五、总结

Druid 核心价值:

  1. 企业级监控:开箱即用的 SQL 监控平台

  2. 安全防护:内置 SQL 防火墙和攻击检测

  3. 生产就绪:经过双十一验证的稳定性

  4. 扩展性强:Filter 机制支持自定义功能

适用场景:

  • 需要全面监控数据库访问的应用

  • 对数据库安全要求高的系统(如金融、电商)

  • 需要 SQL 分析和优化的场景

  • 多数据源、分库分表等复杂架构

配置黄金法则:

  1. 必设参数max-activemax-waitvalidation-query

  2. 安全配置:启用 WallFilter、设置监控密码

  3. 监控配置:开启 stat 过滤器、设置慢 SQL 阈值

  4. 连接管理:启用空闲检测和泄露回收

通过合理配置,Druid 不仅能提供高性能的连接池功能,还能成为数据库访问的监控中心和安全防线,是企业级应用的理想选择。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐