springboot集成DataSource之druid
SpringBoot默认的数据源是:org.apache.tomcat.jdbc.pool.DataSource。但毕竟Druid是Java语言中最好的数据库连接池,并且可以提供强大的监控和扩展功能,因此这里介绍一下springboot如何整合druid。
1. 引入依赖
<!--druid数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
mybatis+mysql驱动依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
2. SpringBoot整合Druid的yml配置文件
spring:
datasource:
name: mysql_test
type: com.alibaba.druid.pool.DruidDataSource
#druid相关配置
druid:
#监控统计拦截的filters
filter: stat,config
driver-class-name: com.mysql.cj.jdbc.Driver
#基本属性
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
#初始化连接数
initial-size: 10
#最小活跃连接数
min-size: 5
#最大活跃连接数
max-active: 20
#获取连接的等待时间
max-wait: 60000
#间隔多久进行一次检查,检查需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
#一个连接在池中最小的生存时间(5分钟)
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'X'
# 空闲时间大于 time-between-eviction-runs-millis检测连接
test-while-idle: true
# 申请连接时是否检测连接(开启影响性能)
test-on-borrow: false
#归还连接时是否检测连接(开启影响性能)
test-on-return: false
#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
#第三发连接池在使用的时候,获取到Connection后,使用完毕,调用关闭方法,并没有将Connection关闭,只是放回到连接池中
#如果调用这个方法,而没有手动关闭PreparedStatement,就可能造成内存溢出,但是JDK1.7实现了AutoCloseable接口,就不需要关闭了
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: -1
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500;config.decrypt=true;config.decrypt.key=XXX
3. DruidDataSource配置属性列表
配置 | 缺省值 | 说明 |
---|---|---|
name | 如果存在多个数据源,监控的时候可以通过名字区分开来。如果没有配置,将自动生成一个名字。 | |
url | 连接数据库的url | |
username | 连接数据库的用户名 | |
password | 连接数据库的密码,如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里 | |
driverClassName | 根据url自动识别 | 数据库驱动 |
initialSize | 0 | 初始化时建立的物理连接个数。初始化发生在显示调用init方法,或者第一次getConnection时 |
maxActive | 8 | 最大的连接池数量 |
maxIdle | 8 | 已废弃,配置后也不再生效 |
minIdle | 最小连接池数量 | |
maxWait | 获取连接的最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。详细看这里 | |
poolPreparedStatement | false | 是否缓存preparedStatement,也就是PSCache,PSCache对支持游标的数据库性能提升巨大。比如oracle。在mysql下建议关闭。 |
maxPoolPreparedStatementPerConnectionSize | -1 | 要启用PSCache,必须配置大于0。当大于0时,poolPreparedStatement将自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以吧这个数组配置大一些。 |
validationQuery | 用来检测连接是否有效的sql,要求是一个查询语句,常有select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 | |
validationQueryTimeout | 单位:秒,检测连接是否有效的超时时间,底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法 | |
testOnBorrow | true | 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 |
testOnReturn | false | 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 |
testWhileIdle | false | 建议配置true,不影响性能,并且保证安全。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 |
timeBetweenEvictionRunsMillis | 1分钟(1.0.14) | 有两个含义:(1)Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接(2)testWhileIdle判断依据。 |
minEvictableIdleTimeMillis | 连接保存空闲而不被驱逐(关闭物理连接)的最长时间 | |
connectionInitSqls | 物理连接初始化的时候执行的sql | |
exceptionSorter | 根据dbtype判断 | 当数据库抛出一些不可恢复异常时,抛弃连接 |
filters | 属性是字符串,通过别名的方式配置扩展插件,常用的插件(1)监控统计:filter:stat(2)日志用的:filter:log4j(3)防御sql注入:filter:wall | |
proxyFilters | 类型是List,如果同时配置了filters和proxyFilters,是组合关系而非替换关系。 | |
connection-properties | 配置连接的信息(开启慢查询,请求密码等) |
4. Druid监控配置
配置druid数据源之后,就可访问http:localhost:8080/druid/index.html进行查看监控页面了。但如何设置监控的配置信息呢?
4.1. 监控身份验证信息
- 在javaConfig中的配置
使用@Configuration+@Bean注解,在java代码中配置spring容器的bean
@Configuration
public class DruidMonitorConfiguration {
//stat [斯达特] 身份 Registration [瑞这死得神] 注册 [注诶得] druid
@Bean
public ServletRegistrationBean DruidStatViewServlet() {
//ServletRegistrationBean提供类的进行注册.
ServletRegistrationBean servletRegistrationBean =
new ServletRegistrationBean(new StatViewServlet(), "/druid2/*");
//白名单
servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
servletRegistrationBean.addInitParameter("deny", "192.168.1.73");
//登录名密码
servletRegistrationBean.addInitParameter("loginUsername", "name");
servletRegistrationBean.addInitParameter("loginPassword", "password");
//是否能够重置数据
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
}
}
可访问http://localhost:8080/druid2/login.html进行访问
- 在配置文件中的配置
也可以在上面的yml配置文件中配置。
spring:
datasource:
name: mysql_test
type: com.alibaba.druid.pool.DruidDataSource
#druid相关配置
druid:
#配置监控页面访问登录名称/密码
stat-view-servlet:
login-username: admin
login-password: password
url-pattern: /yy/*
#禁止手动重置监控数据
reset-enable: false
转换为properties文件:
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.reset-enable=false
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=123456
4.2 Spring监控,对内部各接口调用的监控
spring.datasource.druid.aop-patterns=com.company.project.service.*,
com.company.project.dao.*,com.company.project.controller.*,com.tellme.mapper.*
spring监控效果图
4.2 Druid的慢sql
在sql监控中,有一项关于sql执行最慢时间的统计,但是只要一个值,就是一条sql语句最慢的执行时间记录,其他执行时间是看不到的,只能通过总时间来进行粗略的估计,还存在一个问题:一旦项目重启,这些记录就全都没有,因此制定对应的日志输出策略是及其有必要的。
可以在springboot中可以通过配置文件connection-properties配置慢查询。此时设置的慢sql的时间是1毫秒,所以执行时间大于1毫秒的都会被红色标注。
# 配置StatFilter (开启慢sql)
spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.db-type=h2
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=1
慢查询效果图
附录:
1. 公平锁的效率为什么比非公平锁低
CPU在调度线程的时候,会在等待线程例随机挑选一个线程,由于随机性,故不能保证线程先到先得。这样就会产生饥饿现象:即有些线程优先级低的线程可能永远无法获取CPU的执行权,优先级高的线程会不断抢占资源。于是就有了公平锁。
公平锁可以保证线程按照时间顺序执行,避免饥饿现象的产生,但是公平锁效率很低,因为要保证顺序执行,就得维护一个有序队列。
截取自——Java并发之公平锁
2. mysql下为什么建议关闭poolPreparedStatement
-
第三方的数据库连接池,使用的时候,获取到Connection之后,使用完成,调用的关闭方法(close()) ,并没有将Connection关闭,只是放回到连接池中,如果调用的这个方法,而没有手动关闭PreparedStatement等,则这个PreparedStatement并没有关闭,这样会使得开发的程序内存急速增长,java的内存回收机制可能跟不上速度,最终造成Out of memory Error。
-
如果使用JDK 7就不用了,他们都实现了java.lang.AutoCloseable
截取自——百度知道
文章参考
数据连接池默认配置带来的坑testOnBorrow=false,cloes_wait 终于解决了
(官网)https://github.com/alibaba/druid/wiki/配置_StatViewServlet配置