Druid 参数配置详解

简介

Java 程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池。

  • Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。

  • Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。

  • Druid 已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。

  • Spring Boot 2.0 以上默认使用 Hikari 数据源,Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源。

连接

当我们程序需要访问数据库时,需要创建一个本地到数据库服务的网络连接,此时本地代码就相当于一个数据库的客户端,可以通过这个连接去访问数据、执行sql,如下

Driver driver = new com.mysql.cj.jdbc.Driver();
// 创建连接
Connection con = driver.connect(JDBC_URL, props);
Statement statement = con.createStatement();
ResultSet resultSet = statement.executeQuery("show tables");
while (resultSet.next()) {
    System.out.println(resultSet.getString(1));
}
con.close();

池化技术

由于我们的代码需要不断与数据库交互读取数据,如果每次请求数据都创建一个连接的话,网络开销是很大的,也会导致我们的程序比较慢,同时连接如果太多也会给数据库造成压力

为了解决这个问题,就有了池化技术,把创建好的连接放在池里,用时去池里获取,节省了创建连接的时间,也可以通过配置来限定池的最大连接数等

img

连接池最常用的工具基本就是阿里的Druid了,简单使用如下

// druid 数据源
DruidDataSource druidDataSource = new DruidDataSource();
// 数据源配置
druidDataSource.setUrl(JDBC_URL);
druidDataSource.setUsername(USERNAME);
druidDataSource.setPassword(PASSWORD);
// 初始化
druidDataSource.init();
// 获取表名
Connection con = druidDataSource.getConnection();
Statement statement = con.createStatement();
ResultSet resultSet = statement.executeQuery("show tables");
while (resultSet.next()) {
    System.out.println(resultSet.getString(1));
}
con.close();

可以看到使用了Druid,获取连接不再是直接使用驱动创建连接,而是通过DruidDataSource对象获取连接。

参数配置及说明

配置项名称缺省值说明java set方法定义
connectProperties{}map方式放入自定义的key和value,在Filter等地方可以获取该信息进行相应逻辑控制public void com.alibaba.druid.pool.DruidDataSource.setConnectProperties(java.util.Properties)
connectionPropertiesnull字符串方式放入自定义的key和value,键值对用分号隔开,比如“a=b;c=d”,传入空白字符串表示清空属性,实际拆分字符串后赋值给connectProperties,在Filter等地方可以获取该信息进行相应逻辑控制public void com.alibaba.druid.pool.DruidAbstractDataSource.setConnectionProperties(java.lang.String)
connectTimeout0新增的控制创建连接时的socket连接最大等待超时,单位是毫秒,默认0表示永远等待,工作原理是在创建连接时将该值设置到对应数据库驱动的属性信息中由其JDBC驱动进行控制public void com.alibaba.druid.pool.DruidAbstractDataSource.setConnectTimeout(int)
connectionInitSqls[]数组方式定义物理连接初始化的时候执行的1到多条sql语句,比如连接MySQL数据库使用低版本驱动的情况下,想使用utf8mb4,则可以配置sql为: set NAMES 'utf8mb4'public void com.alibaba.druid.pool.DruidAbstractDataSource.setConnectionInitSqls(java.util.Collection)
createSchedulernull可以使用定时线程池方式异步创建连接,比起默认的单线程创建连接方式,经实际验证这种更可靠public void com.alibaba.druid.pool.DruidAbstractDataSource.setCreateScheduler(java.util.concurrent.ScheduledExecutorService)
dbTypenull对于不是Druid自动适配支持的db类型,可以强制指定db类型,字符串值来自com.alibaba.druid.DbType的枚举名public void com.alibaba.druid.pool.DruidAbstractDataSource.setDbType(java.lang.String)
destroySchedulernull可以使用定时线程池方式异步创建连接,比起默认的单线程创建连接方式,经实际验证这种更可靠public void com.alibaba.druid.pool.DruidAbstractDataSource.setDestroyScheduler(java.util.concurrent.ScheduledExecutorService)
driverClassName根据url自动识别这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassNamecom.alibaba.druid.pool.DruidAbstractDataSource.setDriverClassName(String)
exceptionSorternull当数据库抛出一些不可恢复的异常时,抛弃连接public void com.alibaba.druid.pool.DruidAbstractDataSource.setExceptionSorter(com.alibaba.druid.pool.ExceptionSorter)
failFastfalsenullpublic void com.alibaba.druid.pool.DruidAbstractDataSource.setFailFast(boolean)
filters属性类型是逗号隔开的字符串,通过别名的方式配置扩展插件,插件别名列表请参考druid jar包中的 /META-INF/druid-filter.properties,常用的插件有: 监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall 防御sql注入的filter:wallcom.alibaba.druid.pool.DruidAbstractDataSource.setFilters(String)
initialSize0初始化数据源时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时public void com.alibaba.druid.pool.DruidAbstractDataSource.setInitialSize(int)
keepAlivefalse连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。实际项目中建议配置成truepublic void com.alibaba.druid.pool.DruidDataSource.setKeepAlive(boolean)
keepAliveBetweenTimeMillis120000nullpublic void com.alibaba.druid.pool.DruidAbstractDataSource.setKeepAliveBetweenTimeMillis(long)
logAbandonedfalse在开启removeAbandoned为true的情况,可以开启该设置,druid在销毁未及时关闭的连接时,则会输出日志信息,便于定位连接泄露问题public void com.alibaba.druid.pool.DruidAbstractDataSource.setLogAbandoned(boolean)
loginTimeout单位是秒,底层调用DriverManager全局静态方法java.sql.DriverManager.setLoginTimeout(int)
maxActive8连接池最大活跃连接数量,当连接数量达到该值时,再获取新连接时,将处于等待状态,直到有连接被释放,才能借用成功public void com.alibaba.druid.pool.DruidDataSource.setMaxActive(int)
maxEvictableIdleTimeMillis25200000nullpublic void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxEvictableIdleTimeMillis(long)
maxIdle8已经彻底废弃,配置了也没效果,以maxActive为准public void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxIdle(int)
maxOpenPreparedStatements10nullpublic void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxOpenPreparedStatements(int)
maxPoolPreparedStatementPerConnectionSize10要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100public void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxPoolPreparedStatementPerConnectionSize(int)
maxWait-1获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。public void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxWait(long)
minEvictableIdleTimeMillis1800000连接保持空闲而不被驱逐的最小时间public void com.alibaba.druid.pool.DruidAbstractDataSource.setMinEvictableIdleTimeMillis(long)
minIdle0连接池最小空闲数量public void com.alibaba.druid.pool.DruidAbstractDataSource.setMinIdle(int)
nameDataSource-****配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this). 另外配置此属性至少在1.0.5版本中是不起作用的,强行设置name会出错。详情-点此处public void com.alibaba.druid.pool.DruidAbstractDataSource.setName(java.lang.String)
numTestsPerEvictionRun3不再使用,已经彻底废弃,一个DruidDataSource只支持一个EvictionRunpublic void com.alibaba.druid.pool.DruidAbstractDataSource.setNumTestsPerEvictionRun(int)
passwordnull连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用passwordCallback进行配置,或者使用ConfigFilter。详细看这里public void com.alibaba.druid.pool.DruidAbstractDataSource.setPassword(java.lang.String)
passwordCallbacknull可以自定义实现定制的PasswordCallback,然后实现定制的密码解密效果public void com.alibaba.druid.pool.DruidAbstractDataSource.setPasswordCallback(javax.security.auth.callback.PasswordCallback)
phyTimeoutMillis-1强制回收物理连接的最大超时时长,大于0的情况下才生效,当物理创建之后存活的时长超过该值时,该连接会强制销毁,便于重新创建新连接,建议可以配置成7小时的毫秒值,比如25200000,这样可以规避MySQL的8小时连接断开问题public void com.alibaba.druid.pool.DruidAbstractDataSource.setPhyTimeoutMillis(long)
poolPreparedStatementsfalse是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。public void com.alibaba.druid.pool.DruidDataSource.setPoolPreparedStatements(boolean)
proxyFilters类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系com.alibaba.druid.pool.DruidAbstractDataSource.setProxyFilters(List)
queryTimeout0控制查询结果的最大超时,单位是秒,大于0才生效,最终底层调用是java.sql.Statement.setQueryTimeout(int)public void com.alibaba.druid.pool.DruidAbstractDataSource.setQueryTimeout(int)
removeAbandonedfalse是否回收泄露的连接,默认不开启,建议只在测试环境设置未开启,利用测试环境发现业务代码中未正常关闭连接的情况public void com.alibaba.druid.pool.DruidAbstractDataSource.setRemoveAbandoned(boolean)
removeAbandonedTimeoutMillis300000开启回收泄露连接的最大超时,默认300秒表示连接被借出超过5分钟后,且removeAbandoned开启的情况下,强制关闭该泄露连接public void com.alibaba.druid.pool.DruidAbstractDataSource.setRemoveAbandonedTimeoutMillis(long)
socketTimeout0新增的控制创建连接时的socket最大读超时,单位是毫秒,默认0表示永远等待,配置成10000则表示db操作如果在10秒内未返回应答,将抛出异常,工作原理是在创建连接时将该值设置到对应数据库驱动的属性信息中由其JDBC驱动进行控制public void com.alibaba.druid.pool.DruidAbstractDataSource.setSocketTimeout(int)
testOnBorrowfalse申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,其实一般情况下都可以开启,只有性能要求极其高且连接使用很频繁的情况下才有必要禁用。public void com.alibaba.druid.pool.DruidAbstractDataSource.setTestOnBorrow(boolean)
testOnReturnfalse归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,这个一般不需要开启。public void com.alibaba.druid.pool.DruidAbstractDataSource.setTestOnReturn(boolean)
testWhileIdletrue建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。public void com.alibaba.druid.pool.DruidAbstractDataSource.setTestWhileIdle(boolean)
timeBetweenEvictionRunsMillis60000有两个含义: 1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明public void com.alibaba.druid.pool.DruidAbstractDataSource.setTimeBetweenEvictionRunsMillis(long)
transactionQueryTimeout0控制查询结果的最大超时,单位是秒,大于0才生效,最终是在开启事务的情况下底层调用java.sql.Statement.setQueryTimeout(int)public void com.alibaba.druid.pool.DruidAbstractDataSource.setTransactionQueryTimeout(int)
url连接数据库的url,不同数据库不一样。例如: mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnautocom.alibaba.druid.pool.DruidAbstractDataSource.setUrl(String)
usernamenull连接数据库的用户名public void com.alibaba.druid.pool.DruidAbstractDataSource.setUsername(java.lang.String)
validationQuerynull用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。public void com.alibaba.druid.pool.DruidAbstractDataSource.setValidationQuery(java.lang.String)
validationQueryTimeout-1单位:秒,检测连接是否有效的超时时间,大于0才生效。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法public void com.alibaba.druid.pool.DruidAbstractDataSource.setValidationQueryTimeout(int)

实际配置示例

Spring Boot 方式(推荐)

依赖

    <!--引入druid数据源-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.6</version>
    </dependency>

连接池配置:

spring:
  datasource:
   #数据源基本配置
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_crud
    type: com.alibaba.druid.pool.DruidDataSource
   #数据源其他配置
    druid:
      #配置初始化大小、最小、最大线程数
      initialSize: 5
      minIdle: 5
      #CPU核数+1,也可以大些但不要超过20,数据库加锁时连接过多性能下降
      maxActive: 20
     # 最大等待时间,内网:800,外网:1200(三次握手1s)
      maxWait: 60000
      timeBetweenEvictionRunsMillis: 60000
     #配置一个连接在池中最大空间时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      validationQuery: SELECT 1 
      testWhileIdle: true
     # 设置从连接池获取连接时是否检查连接有效性,true检查,false不检查
      testOnBorrow: true
      # 设置从连接池归还连接时是否检查连接有效性,true检查,false不检查
      testOnReturn: true
      #可以支持PSCache(提升写入、查询效率)
      poolPreparedStatements: true
      #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙  
      filters: stat,wall,log4j
      maxPoolPreparedStatementPerConnectionSize: 20
      useGlobalDataSourceStat: true  
      connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

实现密码加密

目前配置文件中配置的数据库用户名和密码都是明文的,这在某些情况下是不被允许的,那正好druid可以对其进行加密,按以下操作即可:

  • 利用工具类生成加密后密码和公钥
public static void main(String[] args) throws Exception {
        String password = "root123";
        System.out.println("明文密码: " + password);
        String[] keyPair = ConfigTools.genKeyPair(512);
        //私钥
        String privateKey = keyPair[0];
        //公钥
        String publicKey = keyPair[1];
        //用私钥加密后的密文
        password = ConfigTools.encrypt(privateKey, password);

        System.out.println("privateKey:" + privateKey);
        System.out.println("publicKey:" + publicKey);

        System.out.println("password:" + password);

        String decryptPassword = ConfigTools.decrypt(publicKey, password);
        System.out.println("解密后:" + decryptPassword);
    }

运行后得到:

在这里插入图片描述

  • 利用命令加密

    java -cp D:/xxxx/druid-1.2.8/druid-1.2.8.jar com.alibaba.druid.filter.config.ConfigTools root
    
    java -cp D:/xxxx/druid-1.2.8/druid-1.2.8.jar com.alibaba.druid.filter.config.ConfigTools 123456

    注:123456为你数据库的密码

    img

    对我们有用的是publicKey和加密后的password,这个publickey主要是用来解密的秘钥

  • 修改配置文件

用上面得到的密码和publicKey替换配置文件中的密文:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.jdbc.Driver
    publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKXfJyPsQ1rvSQXO+8m1TrIWS5XSSwzwDBIjPGZNbpZ10+Tai7k1GMzF6eufgMNWlNwOHJvxIYwjrts8b4UbSiECAwEAAQ==
    druid:
        url: jdbc:mysql://lcoahost:3306/test1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: ENC(EChlZH6XdPa129Ii3akF/92alTAIifYXdbFJaqKlmcQNF0a/QRoaAook16eO72vw4S4Ut8nXeoGOMdgFkQuW+A==)
      initial-size: 10
      max-active: 100
      min-idle: 10
      max-wait: 60000
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      #validation-query: SELECT 1 FROM DUAL
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        #login-username: admin
        #login-password: admin
      filter:
        stat:
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: false
        wall:
          config:
            multi-statement-allow: true
        config:
          enabled: true 
      connection-properties: config.decrypt=true;config.decrypt.key=${spring.datasource.publicKey}
配置文件跟加密相关的属性
spring.datasource.druid.connection-properties

这个属性配置的value是键值对,其中config.decrypt=true表示要进行解密,config.decrypt.key=${spring.datasource.publicKey}注入要解密需要的公钥

spring.datasource.druid.filter.config.enabled=true

开启configFilter, 这个不开启是没办法进行解密操作的

本文由博客一文多发平台 OpenWrite 发布!

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Druid连接池是一个开源的、高效的数据库连接池,适用于Java应用程序。它能够提供连接池和管理连接的功能,帮助进行数据库连接的管理和优化。 Druid连接池的配置主要包括以下几个方面: 1. 数据源配置:可以通过配置文件或代码来设置数据库相关的属性,如驱动类型、URL、用户名、密码等。这些配置项可以根据具体的数据库类型和环境需求来设置。 2. 连接池参数配置:可以设置连接池的一些基本参数,如初始化连接数、最小连接数、最大连接数等。这些参数会直接影响连接池的性能和资源占用情况,需要根据具体应用的需求进行调整。 3. 连接属性配置:可以设置每个连接的一些属性,如连接超时时间、最大等待时间、是否自动提交等。这些属性可以根据具体需求进行设置,以满足应用程序的要求。 4. 监控配置:可以设置连接池的监控功能,包括连接池的活跃连接数、空闲连接数、执行SQL次数、慢查询次数等。这些监控数据可以通过配置项输出到日志文件或通过JMX暴露出来,以便进行监控和调优。 5. 连接池扩展配置:可以通过配置项来设置连接池的一些扩展功能,如连接池的预处理、过滤器等。这些功能可以提供更灵活的连接管理方式,以满足特定需求。 通过合理配置Druid连接池,可以提高应用程序对数据库连接的管理和利用效率,减少连接泄露和性能问题。但是需要注意的是,配置应遵循最佳实践,并根据实际情况进行调整和优化,以达到最佳的数据库连接池配置效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值