天天看点

springboot hikari连接不释放_芋道 Spring Boot 数据库连接池入门1. 概述2. HikariCP 单数据源3. HikariCP 多数据源4. Druid 单数据源5. Druid 多数据源666. 彩蛋

点击上方“芋道源码”,选择“设为星标”

做积极的人,而不是积极废人!

源码精品专栏

  • 原创 | Java 2020 超神之路,很肝~
  • 中文详细注释的开源项目
  • RPC 框架 Dubbo 源码解析
  • 网络应用框架 Netty 源码解析
  • 消息中间件 RocketMQ 源码解析
  • 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析
  • 作业调度中间件 Elastic-Job 源码解析
  • 分布式事务中间件 TCC-Transaction 源码解析
  • Eureka 和 Hystrix 源码解析
  • Java 并发源码
摘要: 原创出处 http://www.iocoder.cn/Spring-Boot/datasource-pool/ 「芋道源码」欢迎转载,保留摘要,谢谢!
  • 1. 概述
  • 2. HikariCP 单数据源
  • 3. HikariCP 多数据源
  • 4. Druid 单数据源
  • 5. Druid 多数据源
  • 666. 彩蛋

本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labs 的 lab-19 目录。

原创不易,给点个 Star 嘿,一起冲鸭!

1. 概述

在我们的项目中,数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中,主要是

  • Druid ,为监控而生的数据库连接池。
  • HikariCP ,号称性能最好的数据库连接池。

至于怎么选择,两者都非常优秀,不用过多纠结。

  • Spring Boot 2.X 版本,默认采用 HikariCP 。
  • 阿里大规模采用 Druid 。

当然,如下有一些资料,胖友可以阅读参考:

  • 《Druid 连接池介绍》
  • 《为什么 HikariCP 被号称为性能最好的 Java 数据库连接池,如何配置使用》
  • 《alibaba/druid pool analysis》 ,一个小小的“撕逼”。

下面,我们来进行 HikariCP 和 Druid 的入门,会配置单数据源和多数据源情况下的连接池。

2. HikariCP 单数据源

示例代码对应仓库:lab-19-datasource-pool-hikaricp-single 。

在本小节,我们会使用配置一个数据源的 HikariCP 连接池。

艿艿:推荐入门后,可以看看 HikariCP 的文档:https://github.com/brettwooldridge/HikariCP/wiki 。

2.1 引入依赖

pom.xml

文件中,引入相关依赖。

  • 无需主动引入 HikariCP 的依赖。因为在 Spring Boot 2.X 中,

    spring-boot-starter-jdbc

    默认引入

    com.zaxxer.HikariCP

    依赖。

2.2 应用配置文件

application.yml

中,添加 HikariCP 配置,如下:

  • spring.datasource

    配置项下,我们可以添加数据源的通用配置。
  • spring.datasource.hikari

    配置项下,我们可以添加 HikariCP 连接池的自定义配置。然后

    DataSourceConfiguration.Hikari

    会自动化配置 HikariCP 连接池。

HikariCP 更多配置项,可以看看如下表格:s

FROM 《HikariCP 连接池及其在 Spring Boot 中的配置》
配置项 描述 构造器默认值 默认配置validate之后的值 validate重置
autoCommit 自动提交从池中返回的连接 true true -
connectionTimeout 等待来自池的连接的最大毫秒数 SECONDS.toMillis(30) = 30000 30000 如果小于250毫秒,则被重置回30秒
idleTimeout 连接允许在池中闲置的最长时间 MINUTES.toMillis(10) = 600000 600000 如果idleTimeout+1秒>maxLifetime 且 maxLifetime>0,则会被重置为0(代表永远不会退出);如果idleTimeout!=0且小于10秒,则会被重置为10秒
maxLifetime 池中连接最长生命周期 MINUTES.toMillis(30) = 1800000 1800000 如果不等于0且小于30秒则会被重置回30分钟
connectionTestQuery 如果您的驱动程序支持JDBC4,我们强烈建议您不要设置此属性 null null -
minimumIdle 池中维护的最小空闲连接数 -1 10 minIdle<0或者minIdle>maxPoolSize,则被重置为maxPoolSize
maximumPoolSize 池中最大连接数,包括闲置和使用中的连接 -1 10 如果maxPoolSize小于1,则会被重置。当minIdle<=0被重置为DEFAULT_POOL_SIZE则为10;如果minIdle>0则重置为minIdle的值
metricRegistry 该属性允许您指定一个 Codahale / Dropwizard

MetricRegistry

的实例,供池使用以记录各种指标
null null -
healthCheckRegistry 该属性允许您指定池使用的Codahale / Dropwizard HealthCheckRegistry的实例来报告当前健康信息 null null -
poolName 连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置 null HikariPool-1 -
initializationFailTimeout 如果池无法成功初始化连接,则此属性控制池是否将

fail fast

1 1 -
isolateInternalQueries 是否在其自己的事务中隔离内部池查询,例如连接活动测试 false false -
allowPoolSuspension 控制池是否可以通过JMX暂停和恢复 false false -
readOnly 从池中获取的连接是否默认处于只读模式 false false -
registerMbeans 是否注册JMX管理Bean(

MBeans

)
false false -
catalog 为支持

catalog

概念的数据库设置默认

catalog

driver default null -
connectionInitSql 该属性设置一个SQL语句,在将每个新连接创建后,将其添加到池中之前执行该语句。 null null -
driverClassName HikariCP将尝试通过仅基于jdbcUrl的DriverManager解析驱动程序,但对于一些较旧的驱动程序,还必须指定driverClassName null null -
transactionIsolation 控制从池返回的连接的默认事务隔离级别 null null -
validationTimeout 连接将被测试活动的最大时间量 SECONDS.toMillis(5) = 5000 5000 如果小于250毫秒,则会被重置回5秒
leakDetectionThreshold 记录消息之前连接可能离开池的时间量,表示可能的连接泄漏 如果大于0且不是单元测试,则进一步判断:(leakDetectionThreshold < SECONDS.toMillis(2) or (leakDetectionThreshold > maxLifetime && maxLifetime > 0),会被重置为0 . 即如果要生效则必须>0,而且不能小于2秒,而且当maxLifetime > 0时不能大于maxLifetime
dataSource 这个属性允许你直接设置数据源的实例被池包装,而不是让HikariCP通过反射来构造它 null null -
schema 该属性为支持模式概念的数据库设置默认模式 driver default null -
threadFactory 此属性允许您设置将用于创建池使用的所有线程的java.util.concurrent.ThreadFactory的实例。 null null -
scheduledExecutor 此属性允许您设置将用于各种内部计划任务的java.util.concurrent.ScheduledExecutorService实例 null null -

2.3 Application

创建

Application.java

类,配置

@SpringBootApplication

注解即可。代码如下:

通过实现 CommandLineRunner 接口,应用启动完成后,回调

#run(String... args)

方法,输出下 Connection 信息。执行日志如下:

  • 可以看到,HikariDataSource 成功初始化。

3. HikariCP 多数据源

示例代码对应仓库:lab-19-datasource-pool-hikaricp-multiple 。

在本小节,我们会使用配置两个数据源的 HikariCP 连接池。

3.1 引入依赖

和 「2.1 引入依赖」 是一致。

3.2 应用配置文件

application.yml

中,添加 HikariCP 配置,如下:

  • 我们在

    spring.datasource

    配置项下,定义了

    orders

    users

    两个数据源的配置。而每个数据源的配置,和我们在 「2.2 应用配置文件」 是一致的。

3.3 数据源配置类

3.3.1 错误的示例

在网上,我们会看到这样配置多个数据源的配置类。代码如下:

  • 实际上,这样做的话,在部分场景下,会存在问题,这是为什么呢?
  • 我们先来理解这段程序的用途。以

    #ordersDataSource()

    方法为例子:
    • DataSourceBuilder.create().build()

      代码段,会创建一个 DataSource 数据源。
    • 搭配上

      @Bean(name = "ordersDataSource")

      注解,会创建一个名字为

      "ordersDataSource"

      的 DataSource Bean 。这里,我们使用 HikariCP ,所以返回的是 HikariDataSource Bean 。
    • @ConfigurationProperties(prefix = "spring.datasource.orders")

      注解,会将

      "spring.datasource.orders"

      配置项,逐个属性赋值给 DataSource Bean 。
  • 看起来貌似没问题,但是如果每个数据源如果有 HikariCP 的

    "hikari"

    自定义配置项时,它的自定义配置项无法设置到 HikariDataSource Bean 中。因为,

    "spring.datasource.orders.hikari"

    "spring.datasource.orders"

    的第二层属性。而 HikariDataSource 的配置属性在第一层,这就导致无法正确的设置。

虽然存在该问题,但是大多数项目,我们并不会自定义 HikariCP 的

"hikari"

配置项,所以这个问题就偷偷藏起来,**“不存在”**了。

3.3.2 正确的示例

当然,作为入门的示例,艿艿还是希望提供正确的做法。

cn.iocoder.springboot.lab19.datasourcepool.config

包路径下,我们会创建 DataSourceConfig 配置类。代码如下:

  • 这块代码,我们是参考 Spring Boot

    DataSourceConfiguration.Hikari

    配置类来实现的。
  • #ordersDataSourceProperties()

    方法,创建

    "orders"

    数据源的 DataSourceProperties 配置对象。
    • @Primary

      注解,保证项目中有一个主的 DataSourceProperties Bean 。
    • new DataSourceProperties()

      代码段,会创建一个 DataSourceProperties 数据源的配置对象。
    • 搭配上

      @Bean(name = "ordersDataSourceProperties")

      注解,会创建一个名字为

      "ordersDataSourceProperties"

      的 DataSourceProperties Bean 。
    • @ConfigurationProperties(prefix = "spring.datasource.orders")

      注解,会将

      "spring.datasource.orders"

      配置项,逐个属性赋值给 DataSourceProperties Bean 。
  • #ordersDataSource()

    方法,创建

    orders

    数据源。
    • <1.1>

      处,调用

      #ordersDataSourceProperties()

      方法,获得

      orders

      数据源的 DataSourceProperties 。
    • <1.2>

      处,调用

      #createHikariDataSource(DataSourceProperties properties)

      方法,创建 HikariDataSource 对象。这样,

      "spring.datasource.orders"

      配置项,逐个属性赋值给 HikariDataSource Bean 。
    • 搭配上

      @Bean(name = "ordersDataSource")

      注解,会创建一个名字为

      "ordersDataSource"

      的 HikariDataSource Bean 。
    • @ConfigurationProperties(prefix = "spring.datasource.orders.hikari")

      注解,会将 HikariCP 的

      "spring.datasource.orders.hikari"

      自定义配置项,逐个属性赋值给 HikariDataSource Bean 。
  • users

    数据源的配置,同上,就不重复解释了。

3.4 Application

创建

Application.java

类,配置

@SpringBootApplication

注解即可。代码如下:

执行日志如下:

  • 可以看到,两个 HikariDataSource 成功初始化。

多数据源和 JPA、MyBatis、JdbcTemplate 的集成,可以看看 《芋道 Spring Boot 多数据源(读写分离)入门》 文章。

4. Druid 单数据源

示例代码对应仓库:lab-19-datasource-pool-druid-single 。

在本小节,我们会使用配置一个数据源的 Druid 连接池。并简单看看 Druid 的监控功能。

艿艿:推荐入门后,可以看看 Druid 的文档:https://github.com/alibaba/druid/wiki/ 。

4.1 引入依赖

pom.xml

文件中,引入相关依赖。

具体每个依赖的作用,胖友自己认真看下艿艿添加的所有注释噢。S

4.2 应用配置文件

application.yml

中,添加 Druid 配置,如下:

  • spring.datasource

    配置项,设置 Spring 数据源的通用配置。其中,

    spring.datasource.type

    配置项,需要主动设置使用 DruidDataSource 。因为默认情况下,

    spring-boot-starter-jdbc

    的 DataSourceBuilder 会按照

    DATA_SOURCE_TYPE_NAMES

    的顺序,尝试推断数据源的类型。
  • spring.datasource.druid

    配置项,设置 Druid 连接池的自定义配置。然后 DruidDataSourceAutoConfigure 会自动化配置 Druid 连接池。
    • 在 《Druid —— 配置属性》 和 《DruidDataSource 配置属性列表》 下,提供了各种 Druid 的配置项,胖友可以自己看看。
    • filter.stat

      配置项,我们配置了 Druid StatFilter ,用于统计监控信息。对应文档 《Druid —— 配置_StatFilter》 。要注意,StatFilter 并不是我们说的

      javax.servlet.Filter

      ,而是 Druid 提供的 Filter 拓展机制。
    • filter.stat-view-servlet

      配置项,我们配置了 Druid StatViewServlet ,用于提供监控信息的展示的 html 页面和 JSON API 。对应文档 《Druid —— 配置_StatViewServlet 配置》 。StatViewServlet 就是我们说的

      javax.servlet.Filter

4.3 Application

创建

Application.java

类,配置

@SpringBootApplication

注解即可。代码如下:

执行日志如下:

  • 可以看到,DruidDataSource 成功初始化。

4.4 监控功能

因为我们在 「4.2 应用配置中」 中,做了如下操作:

  • 通过

    spring.datasource.filter.stat

    配置了 StatFilter ,统计监控信息。
  • 通过

    spring.datasource.filter.stat-view-servlet

    配置了 StatViewServlet ,提供监控信息的展示的 html 页面和 JSON API 。

所以我们在启动项目后,访问

http://127.0.0.1:8080/druid

地址,可以看到监控 html 页面。如下图所示:

springboot hikari连接不释放_芋道 Spring Boot 数据库连接池入门1. 概述2. HikariCP 单数据源3. HikariCP 多数据源4. Druid 单数据源5. Druid 多数据源666. 彩蛋
  • 在界面的顶部,提供了数据源、SQL 监控、SQL 防火墙等等功能。
  • 每个界面上,可以通过 View JSON API 获得数据的来源。同时,我们可以在 JSON API(

    http://127.0.0.1:8080/druid/api.html

    ) 菜单对应的界面中,看到 StatViewServlet 内置的监控信息的 JSON API 列表。
  • 因为监控信息是存储在 JVM 内存中,在 JVM 进程重启时,信息将会丢失。如果我们希望持久化到 MySQL、Elasticsearch、HBase 等存储器中,可以通过 StatViewServlet 提供的 JSON API 接口,采集监控信息。另外,有个 druid-aggregated-monitor 开源项目,提供了 集中监控分布式服务中的 Druid 连接池的方案和思路。
  • 如果 StatViewServlet 提供的 JSON API 接口,无法满足我们的诉求,我们可以通过自定义 API 接口,使用 DruidStatManagerFacade 获得监控信息。使用示例 DruidStatController 代码如下:
    • 当然,绝大多数情况下,我们并不需要做这方面的拓展。

5. Druid 多数据源

示例代码对应仓库:lab-19-datasource-pool-druid-multiple 。

在本小节,我们会使用配置两个数据源的 Druid 连接池。

5.1 引入依赖

和 「4.1 引入依赖」 是一致。

5.2 应用配置

application.yml

中,添加 Druid 配置,如下:

  • 不同于我们在 「3.2 应用配置文件」 中,我们将 Druid 的自定义配置,和

    url

    driver-class-name

    等数据源的通用配置放在同一级,这样后续我们只需要使用

    @ConfigurationProperties(prefix = "spring.datasource.orders")

    的方式,就能完成 DruidDataSource 的配置属性设置。
  • spring.datasource.druid

    配置项下,我们还是配置了

    filter.stat

    stat-view-servlet

    配置项,用于 Druid 监控功能。

5.3 数据源配置类

cn.iocoder.springboot.lab19.datasourcepool.config

包路径下,我们会创建 DataSourceConfig 配置类。代码如下:

  • 因为我们在 「5.2 应用配置」 中,将 Druid 自定义的配置项,和数据源的通用配置放在了同一级,所以我们只需使用

    @ConfigurationProperties(prefix = "spring.datasource.orders")

    这样的方式即可。
  • 当然,「3.3.2 正确的示例」 也是可以这么做的。实际情况下,比较推荐本小节的方式。

5.4 Application

创建

Application.java

类,配置

@SpringBootApplication

注解即可。代码如下:

执行日志如下:

  • 可以看到,两个 DruidDataSource 成功初始化。

5.5 监控功能

和 「4.4 监控功能」 一致。

不过呢,我们在监控页面上,可以看到两个 Druid 数据库连接池。

666. 彩蛋

艿艿:咳咳咳,瞎哔哔了一些内容,可以选择不看。😜

艿艿在星球里,做了一波目前在使用的连接池的调查,大概比例是 Druid : HikariCP 为 2:1 左右。猜测随着 Spring Boot 2.X 逐步普及之后,HikariCP 有一定几率反超 Druid 。

虽然说,HikariCP 没有直接提供监控功能,但是可以使用 Prometheus 采集 Spring Boot Metrics 的数据,后续使用 Grafana 制作仪表盘。目前,已经有 Spring Boot HikariCP / JDBC 可以直接使用。具体怎么做,胖友可以看看 《Spring Boot 中使用 HikariCP 连接池》 文章。

Druid 的 Issues 3047 中,也有人提出,是否能够提供 Druid 接入 Prometheus 统一监控的诉求。Druid 目前暂时不支持,不过有聪慧的胖友,提出了使用 Prometheus jmx_exporter 的方式,将 Druid 实现的 JMX 格式的指标暴露出来,提供给 Prometheus 采集监控信息。

在编写本文的过程中,无意中看到 Druid 文档中提到,曾经想试验性的提供 分库分表 的功能,而艿艿的记忆中,Sharding-JDBC 曾经也想开发数据库连接池的功能。大体在 DataSource 数据源上做拓展的中间件,可能都不甘于仅仅只覆盖一块需求,而是希望成为一站式的数据库中间件。立个 Flag ,ShardingSphere 可能会提供数据库连接池的组件。

旁白君:Sharding-JDBC 是 ShardingSphere 在 JDBC 层面提供的分库分表组件。当然,不仅仅提供分库分表的功能,也提供读写分离、数据脱敏、分布式事务等等功能。

如果胖友工作的比较早,一定还接触过其它连接池。例如说,c3p0、dbcp、BoneCP 等等。数据库连接池的发展过程,是个非常有意思的历史。感兴趣的胖友,可以看看 《大话数据库连接池简史,你都用过几个?》 一文,江湖味十足~

可能胖友会比较纠结,是否要去自定义连接池的配置呢?一般情况下,默认的配置基本能够满足项目的基本要求,不需要特别刻意去修改。当然,这里推荐看两篇文章:

  • 《DruidDataSource 配置》 ,Druid 官方提供了通用的配置。
  • 《Druid 连接池推荐配置》 ,某公司的内部实践。

欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:

springboot hikari连接不释放_芋道 Spring Boot 数据库连接池入门1. 概述2. HikariCP 单数据源3. HikariCP 多数据源4. Druid 单数据源5. Druid 多数据源666. 彩蛋

已在知识星球更新源码解析如下:

springboot hikari连接不释放_芋道 Spring Boot 数据库连接池入门1. 概述2. HikariCP 单数据源3. HikariCP 多数据源4. Druid 单数据源5. Druid 多数据源666. 彩蛋
springboot hikari连接不释放_芋道 Spring Boot 数据库连接池入门1. 概述2. HikariCP 单数据源3. HikariCP 多数据源4. Druid 单数据源5. Druid 多数据源666. 彩蛋
springboot hikari连接不释放_芋道 Spring Boot 数据库连接池入门1. 概述2. HikariCP 单数据源3. HikariCP 多数据源4. Druid 单数据源5. Druid 多数据源666. 彩蛋
springboot hikari连接不释放_芋道 Spring Boot 数据库连接池入门1. 概述2. HikariCP 单数据源3. HikariCP 多数据源4. Druid 单数据源5. Druid 多数据源666. 彩蛋

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

springboot hikari连接不释放_芋道 Spring Boot 数据库连接池入门1. 概述2. HikariCP 单数据源3. HikariCP 多数据源4. Druid 单数据源5. Druid 多数据源666. 彩蛋

继续阅读