目录

Druid 数据源概述

切换 Druid 数据源

自定义 Druid 数据源参数

配置 Druid 数据源监控

Spring 监控

去除页脚广告

API 获取 Druid 监控数据


Druid 数据源概述

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

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

3、《Spring Boot 默认数据源 HikariDataSource 与 JdbcTemplate》中已经介绍 Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源

4、本文重点介绍 Spring Boot 如何集成 Druid 数据源,如何实现数据库监控。

切换 Druid 数据源

引入 Druid 数据源

1、第一步需要在应用的 pom.xml 文件中添加上 Druid 数据源依赖,可以从 Maven 仓库官网 Maven Repository 中获取.

        <!-- Druid 数据源依赖,集成了 Spring boot ,方便配置 druid 属性 -->
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>

        <!-- Mysql 数据库驱动,spring boot 2.1.3 时,mysql 驱动版本为 8.0.15 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- 引入 Spring Data JPA,JPA 组件内部会依赖 JDBC 组件,JDBC 组件内部默认依赖的是 HikariCP 数据源-->
        <!--切换 druid 数据源时,HikariCP 依赖可以移除掉,不移除时也不影响-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!--引用 log4j2 spring boot 启动器,内部依赖了 slf4j、log4j;排除项目中的 logback-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

pom.xml · 汪少棠/red-door - Gitee.com

切换 Druid 数据源

1、《Spring Boot 默认数据源 HikariDataSource 与 JdbcTemplate中已经说过 Spring Boot 2.0 以上默认使用 com.zaxxer.hikari.HikariDataSource 数据源。

2、但可以 通过 spring.datasource.type 指定数据源,可以从 Spring Boot 官方文档 查看:

spring:
  datasource:
    #jdbc 基本通用配置
    username: root
    password: root
    #高版本的 spring boot 搭配的 mysql 驱动版本通常也较高,如 mysql-connector-java:8.0.X
    #此时 url 的值要带时区 serverTimezone、driver-class-name 的值要带 cj
    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    #切换 Druid 数据源
    type: com.alibaba.druid.pool.DruidDataSource

src/main/resources/application.yml · 汪少棠/red-door - Gitee.com

Druid 数据源测试

1、数据源切换之后,同理可以注入 DataSource,然后获取到它,输出一看便知是否成功切换:

import com.alibaba.druid.pool.DruidDataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
//数据源测试,测试 spring.datasource.xx 的 druid 属性配置是否正常,数据库是否能连接上等等
@RunWith(SpringRunner.class)
@SpringBootTest
public class DataSourceTest {
    //Spring Boot 默认已经配置好了数据源,程序员可以直接 DI 注入然后使用即可
    @Resource
    private DataSource dataSource;

    @Test
    public void contextLoads() throws SQLException {
        System.out.println("数据源>>>>>>" + dataSource.getClass());
        Connection connection = dataSource.getConnection();
        System.out.println("连接>>>>>>>>>" + connection);
        System.out.println("连接地址>>>>>" + connection.getMetaData().getURL());

        if (dataSource instanceof DruidDataSource) {
            DruidDataSource druidDataSource = (DruidDataSource) dataSource;
            System.out.println("druidDataSource 数据源最大连接数:" + druidDataSource.getMaxActive());
            System.out.println("druidDataSource 数据源初始化连接数:" + druidDataSource.getInitialSize());
            System.out.println("version=" + druidDataSource.getVersion());
            System.out.println("name=" + druidDataSource.getName());
        }
        connection.close();
    }

    // 控制台输出默认数据源:
    // 数据源>>>>>>class com.zaxxer.hikari.HikariDataSource
    // 连接>>>>>>>>>HikariProxyConnection@519751097 wrapping com.mysql.cj.jdbc.ConnectionImpl@11a3a45f
    // 连接地址>>>>>jdbc:mysql://127.0.0.1:3306/wang?characterEncoding=UTF-8&serverTimezone=UTC

    // 控制台输出 druid 数据源:
    // 数据源>>>>>>class com.alibaba.druid.pool.DruidDataSource
    // 连接>>>>>>>>>com.mysql.cj.jdbc.ConnectionImpl@6fc1a8f6
    // 连接地址>>>>>jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&serverTimezone=UTC
    // druidDataSource 数据源最大连接数:200
    // druidDataSource 数据源初始化连接数:10
    // version=1.2.8
    // name=druid-db1
}

src/test/java/com/wmx/reddoor/DataSourceTest.java · 汪少棠/red-door - Gitee.com

自定义 Druid 数据源参数

1、Druid 数据源参数配置在全局配置文件中即可,如下所示:

com.alibaba.druid.pool.DruidDataSource 基本配置参数
配置说明

jdbcUrl

(多数据源时使用,单数据源时使用通用的 spring.datasource.url即可)

连接数据库的url,不同数据库不一样。例如: 
mysql : jdbc:mysql://10.20.153.104:3306/druid2 
oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto

username

连接数据库的用户名

(多数据源时使用,单数据源时使用通用的 spring.datasource.username即可)

password

(多数据源时使用,单数据源时使用通用的 spring.datasource.password即可)

连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter

driverClassName

这一项可配可不配,不配置时druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)

(多数据源时使用,单数据源时使用通用的 spring.datasource.driver-class-name即可)

connectionInitSqls物理连接初始化的时候执行的sql
exceptionSorter当数据库抛出一些不可恢复的异常时,抛弃连接
filters属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 
监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
proxyFilters

类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系

spring:
  datasource:
    #jdbc 通用配置,对应的是 org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 中的属性
    username: root
    password: root
    #高版本的 spring boot 搭配的 mysql 驱动版本通常也较高,如 mysql-connector-java:8.0.X
    #此时 url 的值要带时区 serverTimezone、driver-class-name 的值要带 cj
    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    #切换 Druid 数据源
    type: com.alibaba.druid.pool.DruidDataSource

    #druid 数据源专有配置,对应的是 com.alibaba.druid.pool.DruidDataSource 中的属性
    druid:
      #数据源名称:当存在多个数据源时,设置名字可以很方便的来进行区分,默认自动生成名称,格式是:"DataSource-" + System.identityHashCode(this)
      name: druid-db1
      initialSize: 10 #初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时,默认0
      maxActive: 200  #最大连接池数量,默认8
      minIdle: 10     #最小连接池数量
      maxWait: 60000  #获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
      timeBetweenEvictionRunsMillis: 60000 #1)Destroy线程会检测连接的间隔时间2)testWhileIdle的判断依据(详细看testWhileIdle属性的说明)
      minEvictableIdleTimeMillis: 300000   #设置连接最小可收回空闲时间(毫秒),默认为 1000L * 60L * 30L
      maxEvictableIdleTimeMillis: 900000   #设置连接最大可收回空闲时间(毫秒),默认为 1000L * 60L * 60L * 7
      validationQuery: SELECT 1 FROM DUAL #用来检测连接是否有效的sql,求是一个查询语句。默认为null,此时testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
      testWhileIdle: true #申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效,默认为true
      testOnBorrow: false #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,默认false.
      testOnReturn: false #归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,默认false.
      poolPreparedStatements: true #是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
      #要启用PSCache,必须配置大于0,当大于0时, poolPreparedStatements自动触发修改为true,
      #在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
      maxOpenPreparedStatements: 20
      #连接池中的 minIdle 数量以内的连接,空闲时间超过 minEvictableIdleTimeMillis,则会执行 keepAlive 操作
      keepAlive: true
      maxPoolPreparedStatementPerConnectionSize: 20 #每个连接大小的最大池准备语句数
      useGlobalDataSourceStat: true #是否使用全局数据源统计,默认false
      connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 #连接属性
      #配置监控统计的内置过滤器:stat-监控统计(必须配置,否则监控不到sql)、wall-防御sql注入、log4j2-日志记录框架(值与应用中的日志框架保持一致,如 log4j、log4j、logback、slf4j)
      filters: stat,wall,log4j2

src/main/resources/application.yml · 汪少棠/red-door - Gitee.com

2、现在可以重新测试 Druid 数据源,查看配置文件中的参数是否已经生效,也可以直接 Debug 查看 DruidDataSource 的属性。

配置 Druid 数据源监控

1、可以通过 spring.datasource.druid.filters=stat,wall,log4j2 ...的方式来启用相应的内置 Filter,这些内置 Filter 使用的是默认配置。如果默认配置无法满足需求,则可以自定义 Filter,要想使自定义的 Filter 配置生效,则需要将对应 Filter 的 enabled 设置为 true。

spring:
  datasource:
    #druid 数据源专有配置,对应的是 com.alibaba.druid.pool.DruidDataSource 中的属性
    druid:
      ########## 过滤器 ##########
      #配置监控统计的内置过滤器:stat-监控统计(必须配置,否则监控不到sql)、wall-防御sql注入、log4j2-日志记录框架(值与应用中的日志框架保持一致,如 log4j、log4j、slf4j等等)
      filters: stat,wall,log4j2
      #自定义过滤器配置:stat、slf4j、log4j、log4j2、commons-log、wall
      #内置Filter都是默认配置,无法满足需求时,则可以自定义 Filter,自定义的过滤器默认都是没有开启的。
      filter:
        stat: #状态监控过滤器
          enabled: true
          db-type: mysql
          log-slow-sql: true  #开启慢sql监控,超过指定时间则认为是慢sql,记录到日志中
          slow-sql-millis: 5000
        slf4j: #日志监控过滤器,使用slf4j 进行日志输出
          enabled: true
          statement-log-error-enabled: true
          statement-create-after-log-enabled: false
          statement-close-after-log-enabled: false
          result-set-open-after-log-enabled: false
          result-set-close-after-log-enabled: false
        wall: #防火墙过滤器
          enabled: true
          config:
            delete-allow: false     #不允许删除数据
            drop-table-allow: false #不允许删除表

      ########## WebStatFilter:web 状态监控过滤器 ##########
      web-stat-filter:
        enabled: true
        url-pattern: /*                 #过滤所有url
        exclusions: "*.js,*.css,*.gif,*.jpg,*.png,*.ico,/druid/*"   # 排除一些不必要的url
        session-stat-enable: true       #开启session统计功能
        session-stat-max-count: 1000    #session的最大个数,默认100

      ########## StatViewServlet(监控页面路径配置),用于展示Druid的监控统计信息 ##########
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*           #访问内置监控页面的路径,内置监控页面的首页是 http://127.0.0.1:8080/druid/login.html 或者 /druid/index.html
        reset-enable: false             #不允许清空统计数据,重新计算
        login-username: root            #配置监控页面登陆用户
        login-password: 123456          #配置监控页面登陆密码
        allow: 127.0.0.1                #允许访问的地址,如果没有配置或者为空,则允许所有访问
        deny:                           #拒绝访问的地址,deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝

2、WebStatFilter 过滤器用于统计 web 应用请求中所有的数据库信息,比如发出的 sql 语句,sql 执行的时间、请求次数、请求的 url 地址、以及seesion 监控、数据库表的访问次数 等等。

3、StatViewServlet(监控页面路径配置),用于配置 Druid 监控统计页面的登陆地址以及账号密码等信息。

4、启动应用即可访问监控页面首页: http://127.0.0.1:8080/druid/login.html 或者 /druid/index.html

Spring 监控

1、Spring 监控是用于通过 aop 切面对指定类及方法进行监控,首先应用需要引入 Aop 依赖。

<!--SpringBoot 的aop 模块-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、然后配置 Spring 监控 AOP 切入点,配置多个时用英文逗号分隔。切入点表达式语法

 com.wmx..*.controller..*.*:表示 com.wmx 包任意子孙包下面的 controller 包下面任意子孙包中任意类中的任意方法。

spring:
  datasource:
    druid:
      aop-patterns: com.wmx..*.controller..*.* #Spring监控AOP切入点,多个时用英文逗号分隔

去除页脚广告

1、访问监控页面的时候,页面底部(footer)会看到内置的广告,是因为引入的 druid-x.y.z.jar 包中的 common.js 中添加的广告。

2、直接到本地仓库中,找到 druid-x.y.z.jar 包,然后用压缩工具打开,找到 support/http/resources/js/common.js,然后注释掉里面的 this.buildFooter(); 或者修改为自己的页脚内容。

API 获取 Druid 监控数据

1、Druid 的监控数据不仅可以在页面上查看,在 开启 StatFilter 后,也可以通过 DruidStatManagerFacade 进行获取;

2、DruidStatManagerFacade.getDataSourceStatDataList 方法可以获取所有数据源的监控数据,

除此之外 DruidStatManagerFacade 还提供了一些其他方法,可以按需选择使用。

import com.alibaba.druid.stat.DruidStatManagerFacade;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;

//druid 数据源监控信息
@RestController
public class DruidController {

    /**获取 druid 数据监控信息
     * http://127.0.0.1:8080/myDruid/stat
     */
    @GetMapping("myDruid/stat")
    public List<Map<String, Object>> druidStat() {
        List<Map<String, Object>> statDataList = DruidStatManagerFacade.getInstance().getDataSourceStatDataList();
        return statDataList;
    }
}

src/main/java/com/wmx/reddoor/jpa/controller/DruidController.java · 汪少棠/red-door - Gitee.com

返回值如:src/main/resources/DruidStatManagerFacade 获取 druid 数据监控信息.json

参数名值示例描述
ActiveCount2当前连接池中活跃连接数
ActivePeak4连接池中活跃连接数峰值
ActivePeakTime1667698206147活跃连接池峰值出现的时间
BlobOpenCount0Blob 打开数
ClobOpenCount0Clob 打开数
CommitCount79提交数
ConnectionHoldTimeHistogram0,0,0,0,0,0,0,0

连接持有时间分布,分布区间为[0-1 ms, 1-10 ms, 10-100 ms, 100ms-1s, 1-10 s, 10-100 s, 100-1000 s, >1000 s],这个值是一个数组,数值的索引位的含义如上述,第几索引上的数据就代表在这个时间区间内包含的连接数.

DbTypeoracle数据库类型
DefaultAutoCommittrue是否默认提交
DiscardCount0放弃/丢弃的个数
DriverClassNameoracle.jdbc.OracleDriver驱动类
ErrorCount0错误数
ExceptionSorterClassName

com.alibaba.druid.pool.

vendor.OracleExceptionSorter

异常分类器类名
ExecuteBatchCount16执行批次计数
ExecuteCount530执行总数
ExecuteQueryCount503执行查询计数
ExecuteUpdateCount11执行更新计数
FailFastfalse是否快速失败
FilterClassNames[]过滤器类名称
Identity236947638
InitGlobalVariantsfalse初始全局变量
InitVariantsfalse初始变量
InitialSize60连接池建立时创建的初始化连接数
KeepAlivetrue是否保持活跃
KeepAliveCheckCount186保持活动检查计数
LogDifferentThreadtrue记录不同的线程
LogicCloseCount437产生的逻辑连接关闭总数
LogicConnectCount439产生的逻辑连接建立总数
LogicConnectErrorCount0产生的逻辑连接出错总数
LoginTimeout0数据库客户端登录超时时间
MaxActive200连接池中最大的活跃连接数
MaxEvictableIdleTimeMillis25200000最大可收回空闲时间(毫秒)

MaxPoolPreparedStatement-

PerConnectionSize

20每个连接大小的最大池准备语句
MaxWait-1最大等待时间
MaxWaitThreadCount-1最大等待线程计数
MinEvictableIdleTimeMillis3600000最小可执行时间Mill
MinIdle120连接池中最小的活跃连接数
NameDataSource-236947638数据源名称
NotEmptyWaitCount0获取连接时最多等待多少次
NotEmptyWaitMillis0获取连接时最多等待多长时间,毫秒为单位
PSCacheAccessCount486PSCache访问总数
PSCacheHitCount324PSCache命中次数
PSCacheMissCount162PSCache未命中次数
PhysicalCloseCount0产生的物理关闭总数
PhysicalConnectCount5产生的物理连接建立总数
PhysicalConnectErrorCount0产生的物理连接失败总数
PoolPreparedStatementstrue预编译准备语句
PoolingCount3当前连接池中的连接数
PoolingPeak5连接池中连接数的峰值
PoolingPeakTime1667697496829连接池数目峰值出现的时间
PreparedStatementClosedCount99预编译准备语句关闭计数
PreparedStatementOpenCount162准备语句打开计数
QueryTimeout0查询超时数
RecycleErrorCount0回收错误计数
RemoveAbandonedtrue已删除
RollbackCount1回滚数
StartTransactionCount37事务开始的个数
TestOnBorrowfalse参考上面'自定义 Druid 数据源参数'
TestOnReturnfalse参考上面'自定义 Druid 数据源参数'
TestWhileIdletrue参考上面'自定义 Druid 数据源参数'
TransactionHistogram0,7,17,6,0,0,0,0

事务运行时间分布,分布区间为[0-10 ms, 10-100 ms, 100-1 s, 1-10 s, 10-100 s, >100 s],这个值是一个数组,数值的索引位的含义如上述,第几索引上的数据就代表在这个时间区间内包含的事务数。

TransactionQueryTimeout0事务查询超时数
URL

jdbc:oracle:thin:@10.104.65.181:1521/orcl

数据库连接地址
UseUnfairLocktrue使用不公平锁定
UserNamecs_element数据库连接账号

ValidConnection-

CheckerClassName

com.alibaba.druid.pool.

vendor.OracleValidConnectionChecker

有效连接检查器类别名称
WaitThreadCount0当前等待获取连接的线程数

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐