Druid简介(Spring Boot + Mybatis + Druid数据源【官方start】)

Druid的简介

Druid是一个非常优秀的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。

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

Druid是一个JDBC组件,它包括三个部分:

  • 基于Filter-Chain模式的插件体系。

  • DruidDataSource 高效可管理的数据库连接池。

  • SQLParser

Druid的功能

兼容DBCP

Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。从DBCP迁移到Druid,只需要修改数据源的实现类就可以了。

强大的监控特性

Druid内置了一个功能强大的StatFilter插件可以监控数据库访问性能,可以清楚知道连接池和SQL的工作情况。

  • 监控SQL的执行时间、ResultSet持有时间、返回行数、更新行数、错误次数、错误堆栈信息。

  • SQL执行的耗时区间分布。什么是耗时区间分布呢?比如说,某个SQL执行了1000次,其中0-1毫秒区间50次,1-10毫秒800次,10-100毫秒100次,100-1000毫秒30次,1-10秒15次,10秒以上5次。通过耗时区间分布,能够非常清楚知道SQL的执行耗时情况。

  • 监控连接池的物理连接创建和销毁次数、逻辑连接的申请和关闭次数、非空等待次数、PSCache命中率等。

数据库密码加密

直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持PasswordCallback。

SQL执行日志

Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。

扩展JDBC

如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。

Druid在DruidDataSourc和ProxyDriver上提供了Filter-Chain模式的扩展API,类似Serlvet的Filter,配置Filter拦截JDBC的方法调用。

SQLParser

SQL Parser是Druid的一个重要组成部分,它提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。

简单SQL语句用时10微秒以内,复杂SQL用时30微秒。

通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如防御SQL注入(WallFilter)、合并统计没有参数化的SQL(StatFilter的mergeSql)、SQL格式化、分库分表。

http://blog.csdn.net/qq_30444003/article/details/50795116

<style>table th:first-of-type { width: 100px;}</style>

Druid的配置详解

配置 缺省值 说明
name 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this). 另外配置此属性至少在1.0.5版本中是不起作用的,强行设置name会出错。详情-点此处
url 连接数据库的url,不同数据库不一样。例如:<br />mysql : jdbc:mysql://10.20.153.104:3306/druid2<br /> oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username 连接数据库的用户名
password 连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里
driverClassName 根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName
initialSize 0 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive 8 最大连接池数量
maxIdle 8 已经不再使用,配置了也没效果
minIdle 最小连接池数量
maxWait 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatements false 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
maxPoolPreparedStatementPerConnectionSize -1 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
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) 有两个含义:<br />1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。<br />2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
numTestsPerEvictionRun 30分钟(1.0.14) 不再使用,一个DruidDataSource只支持一个EvictionRun
minEvictableIdleTimeMillis 连接保持空闲而不被驱逐的最长时间
connectionInitSqls 物理连接初始化的时候执行的sql
exceptionSorter 根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接
filters 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:<br />监控统计用的filter:stat<br />日志用的filter:log4j<br />防御sql注入的filter:wall
proxyFilters 类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系

Druid源码

https://github.com/alibaba/druid/wiki

Druid常见问题

https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

项目实践

我们使用的是Spring boot + mybatis + Druid(官方start)的架构

目前Spring Boot中默认支持的连接池有dbcp,dbcp2, tomcat, hikari四种连接池。

由于Druid暂时不在Spring Bootz中的直接支持。现在阿里官方对Spring Boot做了优化,写了一个start,我们在Spring Boot项目中直接依赖即可。

导入依赖包

<!-- 数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Mybatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>
<!--Mybatis 分页插件 pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- Druid连接池包 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.1</version>
</dependency>

配置数据源

Druid Start Github地址

application.properties配置信息:

#https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
spring.datasource.druid.url=jdbc:mysql://localhost:3306/ssb_test
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.username=root
spring.datasource.druid.password=root
# 初始化大小,最小,最大
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
# 配置获取连接等待超时的时间
spring.datasource.druid.max-wait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.druid.min-evictable-idle-time-millis=300000
#检测连接是否有效的sql
spring.datasource.druid.validation-query=SELECT 'x'
spring.datasource.druid.validation-query-timeout=60000
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
# PSCache Mysql下建议关闭
spring.datasource.druid.pool-prepared-statements=false
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=-1
#spring.datasource.druid.max-open-prepared-statements= #等价于上面的max-pool-prepared-statement-per-connection-size

#mybatis
#entity扫描的包名
mybatis.type-aliases-package=com.xiaolyuh.domain.model
#Mapper.xml所在的位置
mybatis.mapper-locations=classpath*:/mybaits/*Mapper.xml
#开启MyBatis的二级缓存
mybatis.configuration.cache-enabled=true

#pagehelper
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql

到这里我们数据源就配置好了,写一个测试类我们可以查看数据源是否生效。

测试类

package com.xiaolyuh;

import com.alibaba.fastjson.JSON;
import com.xiaolyuh.config.DruidDataSourceProperty;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;

import javax.sql.DataSource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DataSourceTests {

    @Autowired
    ApplicationContext applicationContext;

    @Test
    public void testDataSource() throws Exception {
        // 获取配置的数据源
        DataSource dataSource = applicationContext.getBean(DataSource.class);
        // 查看配置数据源信息
        System.out.println(dataSource.getClass().getName());
    }

}

打印日志:

com.alibaba.druid.pool.DruidDataSource
{"connectionProperties":"druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000","driverClassName":"com.mysql.jdbc.Driver","filters":"stat,wall,log4j","initialSize":5,"maxActive":20,"maxPoolPreparedStatementPerConnectionSize":-1,"maxWait":60000,"minEvictableIdleTimeMillis":300000,"minIdle":5,"password":"root","poolPreparedStatements":false,"testOnBorrow":false,"testOnReturn":false,"testWhileIdle":true,"timeBetweenEvictionRunsMillis":60000,"url":"jdbc:mysql://localhost:3306/ssb_test","useGlobalDataSourceStat":true,"username":"root","validationQuery":"SELECT 'x'"}
2017-07-02 11:29:04.183  INFO 340 --- [       Thread-2] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@11fc564b: startup date [Sun Jul 02 11:28:58 CST 2017]; root of context hierarchy

Druid监控的配置

下面我们来说一下Druid监控的配置:

application.properties配置:

# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.druid.filters=stat,wall,log4j

使用这个filter的配置,开启对监控的支持。属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:

  • 监控统计用的filter:stat
  • 日志用的filter:log4j
  • 防御sql注入的filter:wall

WebStatFilter配置

在application.properties文件中加入如下配置:

# WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter
#启动项目后访问 http://127.0.0.1:8080/druid
#是否启用StatFilter默认值true
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
#缺省sessionStatMaxCount是1000个
spring.datasource.druid.web-stat-filter.session-stat-max-count=1000
#关闭session统计功能
spring.datasource.druid.web-stat-filter.session-stat-enable=false
#配置principalSessionName,使得druid能够知道当前的session的用户是谁
#如果你session中保存的是非string类型的对象,需要重载toString方法
spring.datasource.druid.web-stat-filter.principalSessionName=xxx.user
#如果user信息保存在cookie中,你可以配置principalCookieName,使得druid知道当前的user是谁
spring.datasource.druid.web-stat-filter.principalCookieName=xxx.user
#druid 0.2.7版本开始支持profile,配置profileEnable能够监控单个url调用的sql列表。
spring.datasource.druid.web-stat-filter.profile-enable=false

StatViewServlet配置

在application.properties文件中加入如下配置:

# StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
#启动项目后访问 http://127.0.0.1:8080/druid
#是否启用StatViewServlet默认值true
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.urlPattern=/druid/*
#禁用HTML页面上的“Reset All”功能
spring.datasource.druid.stat-view-servlet.resetEnable=false
#用户名
spring.datasource.druid.stat-view-servlet.loginUsername=admin
#密码
spring.datasource.druid.stat-view-servlet.loginPassword=admin
#IP白名单(没有配置或者为空,则允许所有访问)
spring.datasource.druid.stat-view-servlet.allow=127.0.0.1,192.168.163.1
#IP黑名单 (存在共同时,deny优先于allow)
spring.datasource.druid.stat-view-servlet.deny=192.168.1.73

打开监控界面

浏览器中输入:http://localhost/druid

输入用户名和密码,上面配置的。

image

源码

https://github.com/wyh-spring-ecosystem-student/spring-boot-student/tree/releases

spring-boot-student-mybatis-druid-2 工程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,423评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,339评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,241评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,503评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,824评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,262评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,615评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,337评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,989评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,300评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,829评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,193评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,753评论 3 230
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,970评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,708评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,295评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,207评论 2 258

推荐阅读更多精彩内容