SpringBoot集成连接池 - 集成数据库Druid连接池

上文介绍默认数据库连接池HikariCP,本文主要介绍SpringBoot集成阿里的Druid连接池的实践; 客观的来说,阿里Druid只能说是中文开源中功能全且广泛的连接池为基础的监控组件,但是(仅从连接池的角度)在生态,维护性,开源规范性,综合性能等方面和HikariCP比还是有很大差距。 @pdai

知识准备

了解Druid连接池。

Druid连接池的定位?

Druid连接池是阿里巴巴开源的数据库连接池项目。Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能。功能强大,能防SQL注入,内置Loging能诊断Hack应用行为。

  • Github项目地址 https://github.com/alibaba/druid
  • 文档 https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
  • 下载 http://repo1.maven.org/maven2/com/alibaba/druid/
  • 监控DEMO http://120.26.192.168/druid/index.html

(更多功能请看后续文章)

简单示例

本示例主要展示SpringBoot2 和 Druid CP的集成,并在SpringBoot集成MySQL - 基于JPA的封装基础增加Druid而成。

POM配置

增加依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.9</version>
</dependency>

yml配置

详细的yml配置如下:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_db?useSSL=false&autoReconnect=true&characterEncoding=utf8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: bfXa4Pt2lUUScy8jakXf
    # Druid datasource
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 初始化大小
      initial-size: 5
      # 最小连接数
      min-idle: 10
      # 最大连接数
      max-active: 20
      # 获取连接时的最大等待时间
      max-wait: 60000
      # 一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 300000
      # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 60000
      # 配置扩展插件:stat-监控统计,log4j-日志,wall-防火墙(防止SQL注入),去掉后,监控界面的sql无法统计
      filters: stat,wall
      # 检测连接是否有效的 SQL语句,为空时以下三个配置均无效
      validation-query: SELECT 1
      # 申请连接时执行validationQuery检测连接是否有效,默认true,开启后会降低性能
      test-on-borrow: true
      # 归还连接时执行validationQuery检测连接是否有效,默认false,开启后会降低性能
      test-on-return: true
      # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效,默认false,建议开启,不影响性能
      test-while-idle: true
      # 是否开启 StatViewServlet
      stat-view-servlet:
        enabled: true
        # 访问监控页面 白名单,默认127.0.0.1
        allow: 127.0.0.1
        login-username: admin
        login-password: admin
      # FilterStat
      filter:
        stat:
          # 是否开启 FilterStat,默认true
          enabled: true
          # 是否开启 慢SQL 记录,默认false
          log-slow-sql: true
          # 慢 SQL 的标准,默认 3000,单位:毫秒
          slow-sql-millis: 5000
          # 合并多个连接池的监控数据,默认false
          merge-sql: false
  jpa:
    open-in-view: false
    generate-ddl: false
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQLDialect
        format_sql: true
        use-new-id-generator-mappings: false

更多的配置,请参考官方配置在新窗口打开

测试

访问http://localhost:8080/druid/datasource.html

admin/admin登录

访问接口,进行SQL查询

SQL和慢查询监控

进一步理解

进一步理解下阿里的Druid。

更多功能等

Druid连接池最初就是为监控系统采集jdbc运行信息而生的,它内置了StatFilter 功能,能采集非常完备的连接池执行信息Druid连接池内置了能和Spring/Servlet关联监控的实现,使得监控Web应用特别方便Druid连接池内置了一个监控页面,提供了非常完备的监控信息,可以快速诊断系统的瓶颈。更多请参考:Druid 的GitHub仓库wiki在新窗口打开

监控信息采集的StatFilter

Druid连接池的监控信息主要是通过StatFilter 采集的,采集的信息非常全面,包括SQL执行、并发、慢查、执行时间区间分布等。具体配置可以看这个 https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatFilter

  • 监控不影响性能

Druid增加StatFilter之后,能采集大量统计信息,同时对性能基本没有影响。StatFilter对CPU和内存的消耗都极小,对系统的影响可以忽略不计。监控不影响性能是Druid连接池的重要特性。

  • SQL参数化合并监控

实际业务中,如果SQL不是走PreparedStatement,SQL没有参数化,这时SQL需要参数化合并监控才能真实反映业务情况。如下SQL:

select * from t where id = 1
select * from t where id = 2
select * from t where id = 3

参数化后:

select * from t where id = ?

参数化合并监控是基于SQL Parser语法解析实现的,是Druid连接池独一无二的功能。

  • 执行次数、返回行数、更新行数和并发监控

StatFilter能采集到每个SQL的执行次数、返回行数总和、更新行数总和、执行中次数和和最大并发。并发监控的统计是在SQL执行开始对计数器加一,结束后对计数器减一实现的。可以采集到每个SQL的当前并发和采集期间的最大并发。

  • 慢查监控

缺省执行耗时超过3秒的被认为是慢查,统计项中有包括每个SQL的最后发生的慢查的耗时和发生时的参数。

  • Exception监控

如果SQL执行时抛出了Exception,SQL统计项上会Exception有最后的发生时间、堆栈和Message,根据这些信息可以很容易定位错误原因。

诊断支持

Druid连接池内置了LogFilter,将Connection/Statement/ResultSet相关操作的日志输出,可以用于诊断系统问题,也可以用于Hack一个不熟悉的系统。

LogFilter可以输出连接申请/释放,事务提交回滚,Statement的Create/Prepare/Execute/Close,ResultSet的Open/Next/Close,通过LogFilter可以详细诊断一个系统的Jdbc行为。

LogFilter有Log4j、Log4j2、Slf4j、CommsLog等实现,具体配置看这里 https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_LogFilter

防SQL注入

SQL注入攻击是黑客对数据库进行攻击的常用手段,Druid连接池内置了WallFilter 提供防SQL注入功能,在不影响性能的同时防御SQL注入攻击。

  • 基于语意的防SQL注入

Druid连接池内置了一个功能完备的SQL Parser,能够完整解析mysql、sql server、oracle、postgresql的语法,通过语意分析能够精确识别SQL注入攻击。

  • 极低的漏报率和误报率

基于SQL语意分析,大量应用和反馈,使得Druid的防SQL注入拥有极低的漏报率和误报率。

  • 防注入对性能影响极小

内置参数化后的Cache、高性能手写的Parser,使得打开防SQL注入对应用的性能基本不受影响。

如何评价阿里的Druid连接池

客观的来说,阿里Druid只能说是中文开源中功能全且广泛的连接池为基础的监控组件,但是(仅从连接池的角度)在生态,维护性,开源规范性,综合性能等方面和HikariCP比还是有很大差距。(以下是pdai本人观点,对国产开源并没偏见!)。

首先,仅从功能在新窗口打开上看,Druid并不是一个存粹的连接池,它还承载了监控,诊断,安全的功能。从产品的角度看,all in one 也是有代价的,如果我只期望使用连接池的功能,其它的功能对于使用者来说就是鸡肋;而我们没有看到其长期架构设计(比如插拔式架构,分包设计等), 大概率是当时Druid这种开源的驱动方式并不是一个完善规范的开源软件开发方式(比如KPI driven和个人主义色彩)

(如果你仅仅从功能上比较,你就已经输了,因为这种比较根本不在一个维度上;看到druid主要作者wenshao和hikari作者的讨论在新窗口打开,读者自行辨别~)

文档的规范性,发包规范性,bug修复,生态构建等方面国产开源在那时(当下及未来一段时间)还有很长的路要走。

来看看相关Isusse,2k多个issues哈,没有专职维护(图中Spring的高危漏洞无人修正)

源代码中当前版本是1.2.8,实际版本

实际mvn repo中已经是1.2.9

再看wiki,有些链接居然是空的...

最新的Springboot-starter中SpringBoot还是1.5.12-RELEASE版本,先不说没有支持SpringBoot 2.x版本;高危漏洞无人持续维护,对于开发者而言就是坑(不禁让我又想起了FastJson,说多了都是泪)!

此外,广告都加到UI上了(KPI压力?)

只能说,国产开源在还有很长的路要走!

示例源码

https://github.com/realpdai/tech-pdai-spring-demos