细数 SpringBoot 中的连接池

开发 前端
Druid连接池在性能、监控、诊断、安全、扩展性这些方面远远超出竞品

[[313801]]

 这是Java极客技术的第312篇原创文章

hello~各位读者新年好,我是鸭血粉丝(大家会亲切的喊我「阿粉」),是一位喜欢吃鸭血粉丝的程序员!

回想起前几天在部署springboot项目到正线时,线上环境要求jdk7,可项目是基于jdk8开发的,springboot也是用的springboot2以上的版本,可以说缝缝补补一整天才搞好能满足线上环境的代码,搞完后当然需要小小的了解一下背后的秘密。

好了,话不多说,我们直接进入正题。

其实切换还不算太麻烦,坑就坑在SpringBoot2切换到SpringBoot1后,默认使用的连接池发生了变化,之前做的压力测试又重新搞了一遍

 

怨天尤人貌似消极了哈,阿粉我可是一个正能量满满的人,所以总结下自己就是:虽然会用,但是没了解技术背后的真相而闹出的乌龙。

 

接下里我们就一起来检验下SpringBoot2和SpringBoot1使用的默认数据源吧!

一、SpringBoot2的HikariCP首先在pom文件中需要引入的依赖包:

  1. <parent> 
  2.         <groupId>org.springframework.boot</groupId> 
  3.         <artifactId>spring-boot-starter-parent</artifactId> 
  4.         <version>2.0.4.RELEASE</version> 
  5.     </parent> 
  6.  
  7.     <properties> 
  8.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
  9.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
  10.         <java.version>1.8</java.version> 
  11.         <mybatis.spring.boot.version>1.3.1</mybatis.spring.boot.version> 
  12.     </properties> 
  13.  
  14.     <dependencies> 
  15.         <dependency> 
  16.             <groupId>org.springframework.boot</groupId> 
  17.             <artifactId>spring-boot-starter</artifactId> 
  18.         </dependency> 
  19.         <dependency> 
  20.             <groupId>org.springframework.boot</groupId> 
  21.             <artifactId>spring-boot-starter-web</artifactId> 
  22.         </dependency> 
  23.         <dependency> 
  24.             <groupId>mysql</groupId> 
  25.             <artifactId>mysql-connector-java</artifactId> 
  26.         </dependency> 
  27.         <dependency> 
  28.             <groupId>org.mybatis.spring.boot</groupId> 
  29.             <artifactId>mybatis-spring-boot-starter</artifactId> 
  30.             <version>${mybatis.spring.boot.version}</version> 
  31.         </dependency> 
  32.         <dependency> 
  33.             <groupId>org.projectlombok</groupId> 
  34.             <artifactId>lombok</artifactId> 
  35.         </dependency> 
  36.  
  37.     </dependencies> 

其次在配置文件中需要定义如下属性(不定义时会自动使用默认值)

  1. # spring的相关配置 
  2. spring: 
  3.   application: 
  4.     name: HikariCP测试 
  5.   # 数据源的配置 
  6.   datasource: 
  7.     # 连接池的配置 
  8.     type: com.zaxxer.hikari.HikariDataSource 
  9.     hikari: 
  10.       minimum-idle: 5 
  11.       maximum-pool-size: 15 
  12.       connection-test-query: SELECT 1 
  13.       max-lifetime: 1800000 
  14.       connection-timeout: 30000 
  15.       pool-name: DatebookHikariCP 

配置好后,启动成功时你能看到类似这样子的打印信息:

  1. 2020-01-16 16:23:12.911  INFO 9996 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup 
  2. 2020-01-16 16:23:12.913  INFO 9996 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure 
  3. 2020-01-16 16:23:12.924  INFO 9996 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource] 
  4. 2020-01-16 16:23:12.994  INFO 9996 --- [ main ] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 18001 (http) with context path '' 
  5. 2020-01-16 16:23:13.002  INFO 9996 --- [ main ] c.j.mmzsblog.DatasourceTestApplication   : Started DatasourceTestApplication in 6.724 seconds (JVM running for 8.883) 

其中第3行[com.zaxxer.hikari:name=dataSource,type=HikariDataSource]这部分就点明了使用的连接池类型

二、SpringBoot1的tomcat-jdbc降低版本后,我没有看到上面的信息打印,一时差点不知道使用了什么连接池,不过网上都说是tomcat-jdbc;但是相信眼见为实的我,肯定要在哪里打印一下才放心,于是乎,我进行了如下操作:

搞了一个controller来简单的打印一下连接池的信息

  1. @RestController 
  2. public class testController { 
  3.  
  4.     @Resource 
  5.     private DataSource dataSource; 
  6.  
  7.     @GetMapping("/query"
  8.     public void query(){ 
  9.         System.out.println("查询到的数据源连接池信息是:"+dataSource); 
  10.         System.out.println("查询到的数据源连接池类型是:"+dataSource.getClass()); 
  11.         System.out.println("查询到的数据源连接池名字是:"+dataSource.getPoolProperties().getName()); 
  12.     } 

 

然后我就看到了如下的打印信息,果真是用的tomcat-jdbc

 

  1. 查询到的数据源连接池信息是:org.apache.tomcat.jdbc.pool.DataSource@181d8899{ConnectionPool[defaultAutoCommit=null; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=com.mysql.jdbc.Driver; maxActive=100; maxIdle=100; minIdle=10; initialSize=10; maxWait=30000; testOnBorrow=true; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=false; testOnConnect=falsepassword=********; url=jdbc:mysql://localhost:3306/xxxxxx; username=xxxx; validationQuery=SELECT 1; validationQueryTimeout=-1; validatorClassName=null; validationInterval=3000; accessToUnderlyingConnectionAllowed=true; removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null; initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true; abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null; suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false; useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false; ignoreExceptionOnPreLoad=false; useStatementFacade=true; } 
  2. 查询到的数据源连接池类型是:class org.apache.tomcat.jdbc.pool.DataSource 
  3. 查询到的数据源连接池名字是:Tomcat Connection Pool[1-1715657818] 

其实,我们从pom文件也能看出其中的门道:

  1. <dependency> 
  2.        <groupId>org.springframework.boot</groupId> 
  3.        <artifactId>spring-boot-starter-jdbc</artifactId> 
  4.    </dependency> 

依赖文件中的这一个依赖其实就是表明了SpringBoot1使用的是tomcat-jdbc连接池。

哎,现在才知道SpringBoot2.0和SpringBoot1.0版本使用的默认数据库是不一样的。

现在原因是找到了,可是如何解决呢?要不然把SpringBoot1版本的默认连接池修改成和SpringBoot2版本的一样。好,有了想法,那就开干。

 

 

 

[[313802]]

 

其实,在SpringBoot1的版本也是可以使用HikariCP连接池的,操作就是:

首先引入默认配置的数据源处排除掉tomcat-jdbc

  1. <!--配置默认数据源 --> 
  2.         <dependency> 
  3.             <groupId>org.springframework.boot</groupId> 
  4.             <artifactId>spring-boot-starter-jdbc</artifactId> 
  5.             <exclusions> 
  6.                 <!-- 排除默认的tomcat-jdbc数据源 --> 
  7.                 <exclusion> 
  8.                     <groupId>org.apache</groupId> 
  9.                     <artifactId>tomcat-jdbc</artifactId> 
  10.                 </exclusion> 
  11.             </exclusions> 
  12.         </dependency> 
  13.         <!-- 引用SpringBoot2默认的HikariCP数据源 --> 
  14.         <dependency> 
  15.             <groupId>com.zaxxer</groupId> 
  16.             <artifactId>HikariCP</artifactId> 
  17.             <version>3.3.1</version> 
  18.         </dependency> 

再在.yml文件中配置HikariCP数据源的相关信息

  1. # spring的相关配置 
  2. spring: 
  3.   # 数据源的配置 
  4.   datasource: 
  5.     # 连接池的配置 
  6.     type: com.zaxxer.hikari.HikariDataSource 
  7.     hikari: 
  8.       minimum-idle: 5 
  9.       maximum-pool-size: 15 
  10.       connection-test-query: SELECT 1 
  11.       max-lifetime: 1800000 
  12.       connection-timeout: 30000 

 

为什么说我此处要将数据源切换成SpringBoot2.0使用的默认数据源呢?因为使用SpringBoot1.0的tomcat-jdbc数据源我怕压力测试出来达不到要求,为了不给测试增加工作压力(阿粉我就是这么好的一个人)

 

所以我进行了上面的替换操作。

 

不过这样做肯定也是有好处的。好处就在于HikariCP那迷人的优势:

1、字节码级别优化(很多方法通过JavaAssist生成)

2、大量小改进

用FastStatementList代替ArrayList

无锁集合ConcurrentBag

代理类的优化(比如:,用invokestatic代替invokevirtual)

正如官网的这个对比图显示的一样:它更快

 

 

 

 

其实话又说回来,要是我一开始就是用第三方数据库,岂不是就不存在这些自己搞出来的幺蛾子了!

 

 

 

[[313803]]

 

比如阿里巴巴的Druid连接池不就是个优秀的产品么!它到底有多优秀呢?你先看它的使用:

三、其它连接池(如:Druid)3.1、SpringBoot1.0中引用Druid

和前文的SpringBoot1.0中引用HikariCP一样,先排除默认数据源tomcat-jdbc再引用想要使用的连接池

3.1.1、首先引入默认配置的数据源处排除掉tomcat-jdbc

  1. <!--配置默认数据源 --> 
  2.         <dependency> 
  3.             <groupId>org.springframework.boot</groupId> 
  4.             <artifactId>spring-boot-starter-jdbc</artifactId> 
  5.             <exclusions> 
  6.                 <!-- 排除默认的tomcat-jdbc数据源 --> 
  7.                 <exclusion> 
  8.                     <groupId>org.apache</groupId> 
  9.                     <artifactId>tomcat-jdbc</artifactId> 
  10.                 </exclusion> 
  11.             </exclusions> 
  12.         </dependency> 
  13.         <!-- 引用阿里巴巴的druid数据源 --> 
  14.         <dependency> 
  15.             <groupId>com.alibaba</groupId> 
  16.             <artifactId>druid-spring-boot-starter</artifactId> 
  17.             <version>1.1.10</version> 
  18.         </dependency> 
  19.         <dependency> 
  20.             <groupId>com.alibaba</groupId> 
  21.             <artifactId>druid</artifactId> 
  22.             <version>1.0.31</version> 
  23.         </dependency> 

3.1.2、再在.yml文件中配置Druid数据源的相关信息

  1. spring: 
  2.   # 数据源的配置 
  3.   datasource: 
  4.     # 连接池的配置 
  5.     type: com.alibaba.druid.pool.DruidDataSource             
  6.     druid: 
  7.       initial-size: 5 
  8.       max-active: 10 
  9.       min-idle: 5 
  10.       max-wait: 30000 
  11.       pool-prepared-statements: true 
  12.       max-pool-prepared-statement-per-connection-size:  20 
  13.       validation-query: SELECT 1 FROM DUAL 
  14.       validation-query-timeout: 60000 
  15.       test-on-borrow: false 
  16.       test-on-returnfalse 
  17.       test-while-idle: true 
  18.       time-between-eviction-runs-millis:  60000 
  19.       min-evictable-idle-time-millis: 100000 

 

3.1.3、再写个配置类加载数据源

  1. @Configuration 
  2. @ConditionalOnClass(DruidDataSource.class) 
  3. @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.alibaba.druid.pool.DruidDataSource", matchIfMissing = true
  4. public class DataSourceConfig { 
  5.  
  6.     @Bean 
  7.     @ConfigurationProperties("spring.datasource.druid"
  8.     public DataSource dataSourceOne() { 
  9.         return DruidDataSourceBuilder.create().build(); 
  10.     } 

 

3.1.4、启动效果:

  1. 2020-01-17 16:59:32.804  INFO 8520 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup 
  2. 2020-01-17 16:59:32.806  INFO 8520 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSourceOne' has been autodetected for JMX exposure 
  3. 2020-01-17 16:59:32.808  INFO 8520 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'statFilter' has been autodetected for JMX exposure 
  4. 2020-01-17 16:59:32.818  INFO 8520 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSourceOne': registering with JMX server as MBean [com.alibaba.druid.spring.boot.autoconfigure:name=dataSourceOne,type=DruidDataSourceWrapper] 
  5. 2020-01-17 16:59:32.822  INFO 8520 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'statFilter': registering with JMX server as MBean [com.alibaba.druid.filter.stat:name=statFilter,type=StatFilter] 
  6. 2020-01-17 16:59:32.932  INFO 8520 --- [ main ] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 18001 (http) 
  7. 2020-01-17 16:59:32.943  INFO 8520 --- [ main ] c.j.mmzsblog.DatasourceTestApplication   :  

 

3.2、SpringBoot2.0中引用Druid

在SpringBoot2.0中引用Druid和在SpringBoot1.0中引入类似;

3.2.1、不需要排除默认配置的数据源,直接引入置Druid数据源

  1. <!-- 引用阿里巴巴的druid数据源 --> 
  2.         <dependency> 
  3.             <groupId>com.alibaba</groupId> 
  4.             <artifactId>druid-spring-boot-starter</artifactId> 
  5.             <version>1.1.10</version> 
  6.         </dependency> 
  7.         <dependency> 
  8.             <groupId>com.alibaba</groupId> 
  9.             <artifactId>druid</artifactId> 
  10.             <version>1.0.31</version> 
  11.         </dependency> 

3.2.2、在.yml文件中配置的Druid数据源的相关信息同3.1.3一样

3.2.3、再写个配置类加载数据源同3.1.3一样

3.2.4、启动后你同样能看到打印出类似的信息

  1. Located MBean 'dataSourceOne': registering with JMX server as MBean [com.alibaba.druid.spring.boot.autoconfigure:name=dataSourceOne,type=DruidDataSourceWrapper] 

 

3.3、优秀在哪?

看了上面的使用,超级简单又木有?

首先我们看看druid官网给出的几个传统连接池之间的对比吧:

 

从上表可以看出,Druid连接池在性能、监控、诊断、安全、扩展性这些方面远远超出竞品。

 

 

官网是这样介绍它的:

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

所以,阿粉我倒腾了这么久,想明白了一件事,我以后还是用阿里爸爸的Druid连接池吧,接入简单,还自带监控,并且它可是经过阿里巴巴各大系统考验过的产品,值得信赖,省事省心啊。

责任编辑:武晓燕 来源: Java极客技术
相关推荐

2019-12-30 15:30:13

连接池请求PHP

2022-02-21 07:48:54

Mysql数据库SpringBoot

2009-06-17 09:59:46

Hibernate 连

2010-06-25 10:36:27

Java连接池

2011-06-01 13:54:10

MySQL

2018-02-07 16:23:58

连接池内存池AI

2009-09-22 16:04:50

Hibernate连接

2009-09-22 14:52:55

Hibernate p

2022-11-11 09:41:04

连接池微服务数据库

2009-06-17 16:22:45

Hibernate连接

2010-05-17 16:38:08

MySQL 连接池

2011-05-13 09:34:51

TomcatMysql连接池

2011-07-04 09:39:25

java连接池

2009-07-15 11:00:48

proxool连接池

2015-04-27 09:50:45

Java Hibern连接池详解

2009-12-25 15:38:12

ADO连接池

2009-06-24 07:53:47

Hibernate数据

2022-07-19 13:51:47

数据库Hikari连接池

2010-01-05 10:11:23

ADO.NET连接池

2019-11-27 10:31:51

数据库连接池内存
点赞
收藏

51CTO技术栈公众号