細數springboot中的那些鏈接池

hello~各位讀者新年好!java

回想起前幾天在部署springboot項目到正線時,線上環境要求jdk7,可項目是基於jdk8開發的,springboot也是用的springboot2以上的版本,能夠說縫縫補補一成天才搞好能知足線上環境的代碼,搞完後固然須要小小的瞭解一下背後的祕密。mysql

好了,話很少說,咱們直接進入正題。git

其實切換還不算太麻煩,坑就坑在SpringBoot2切換到SpringBoot1後,默認使用的鏈接池發生了變化,以前作的壓力測試又從新搞了一遍。github

怨天尤人貌似消極了哈,小編我但是一個正能量滿滿的人,因此總結下本身就是:雖然會用,可是沒了解技術背後的真相而鬧出的烏龍。web

接下里咱們就一塊兒來檢驗下SpringBoot2和SpringBoot1使用的默認數據源吧!spring

1、SpringBoot2的HikariCP

  • 首先在pom文件中須要引入的依賴包:
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <mybatis.spring.boot.version>1.3.1</mybatis.spring.boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>複製代碼
  • 其次在配置文件中須要定義以下屬性(不定義時會自動使用默認值)
# spring的相關配置
spring:
  application:
    name: HikariCP測試
  # 數據源的配置
  datasource:
    # 鏈接池的配置
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 5
      maximum-pool-size: 15
      connection-test-query: SELECT 1
      max-lifetime: 1800000
      connection-timeout: 30000
      pool-name: DatebookHikariCP複製代碼

  • 配置好後,啓動成功時你能看到相似這樣子的打印信息:
2020-01-16 16:23:12.911  INFO 9996 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
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
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]
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 ''
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]這部分就點明瞭使用的鏈接池類型sql

2、SpringBoot1的tomcat-jdbc

下降版本後,我沒有看到上面的信息打印,一時差點不知道使用了什麼鏈接池,不過網上都說是tomcat-jdbc;可是相信眼見爲實的我,確定要在哪裏打印一下才放心,因而乎,我進行了以下操做:數據庫

搞了一個controller來簡單的打印一下鏈接池的信息apache

@RestController
public class testController {

    @Resource
    private DataSource dataSource;

    @GetMapping("/query")
    public void query(){
        System.out.println("查詢到的數據源鏈接池信息是:"+dataSource);
        System.out.println("查詢到的數據源鏈接池類型是:"+dataSource.getClass());
        System.out.println("查詢到的數據源鏈接池名字是:"+dataSource.getPoolProperties().getName());
    }
}複製代碼

而後我就看到了以下的打印信息,果然是用的tomcat-jdbctomcat

查詢到的數據源鏈接池信息是: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=false; password=********; 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; }
查詢到的數據源鏈接池類型是:class org.apache.tomcat.jdbc.pool.DataSource
查詢到的數據源鏈接池名字是:Tomcat Connection Pool[1-1715657818]複製代碼

其實,咱們從pom文件也能看出其中的門道:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>複製代碼

依賴文件中的這一個依賴其實就是代表了SpringBoot1使用的是tomcat-jdbc鏈接池。

哎,如今才知道SpringBoot2.0和SpringBoot1.0版本使用的默認數據庫是不同的。

如今緣由是找到了,但是如何解決呢?要否則把SpringBoot1版本的默認鏈接池修改爲和SpringBoot2版本的同樣。好,有了想法,那就開幹。

其實,在SpringBoot1的版本也是可使用HikariCP鏈接池的,操做就是:

  • 首先引入默認配置的數據源處排除掉tomcat-jdbc
<!--配置默認數據源 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <exclusions>
                <!-- 排除默認的tomcat-jdbc數據源 -->
                <exclusion>
                    <groupId>org.apache</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 引用SpringBoot2默認的HikariCP數據源 -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>3.3.1</version>
        </dependency>複製代碼

  • 再在.yml文件中配置HikariCP數據源的相關信息
# spring的相關配置
spring:
  # 數據源的配置
  datasource:
    # 鏈接池的配置
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 5
      maximum-pool-size: 15
      connection-test-query: SELECT 1
      max-lifetime: 1800000
      connection-timeout: 30000複製代碼

爲何說我此處要將數據源切換成SpringBoot2.0使用的默認數據源呢?由於使用SpringBoot1.0的tomcat-jdbc數據源我怕壓力測試出來達不到要求,爲了避免給測試增長工做壓力(小編我就是這麼好的一我的)

因此我進行了上面的替換操做。

不過這樣作確定也是有好處的。好處就在於HikariCP那迷人的優點:

  • 一、字節碼級別優化(不少方法經過JavaAssist生成)
  • 二、大量小改進
    • 用FastStatementList代替ArrayList
    • 無鎖集合ConcurrentBag
    • 代理類的優化(好比:,用invokestatic代替invokevirtual)

正如官網的這個對比圖顯示的同樣:它更快

其實話又說回來,要是我一開始就是用第三方數據庫,豈不是就不存在這些本身搞出來的幺蛾子了!

好比阿里巴巴的Druid鏈接池不就是個優秀的產品麼!它到底有多優秀呢?你先看它的使用:

3、其它鏈接池(如:Druid)

3.一、SpringBoot1.0中引用Druid

和前文的SpringBoot1.0中引用HikariCP同樣,先排除默認數據源tomcat-jdbc再引用想要使用的鏈接池

  • 3.1.一、首先引入默認配置的數據源處排除掉tomcat-jdbc
<!--配置默認數據源 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <exclusions>
                <!-- 排除默認的tomcat-jdbc數據源 -->
                <exclusion>
                    <groupId>org.apache</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 引用阿里巴巴的druid數據源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.31</version>
        </dependency>複製代碼

  • 3.1.二、再在.yml文件中配置Druid數據源的相關信息
spring:
  # 數據源的配置
  datasource:
    # 鏈接池的配置
    type: com.alibaba.druid.pool.DruidDataSource            
    druid:
      initial-size: 5
      max-active: 10
      min-idle: 5
      max-wait: 30000
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size:  20
      validation-query: SELECT 1 FROM DUAL
      validation-query-timeout: 60000
      test-on-borrow: false
      test-on-return: false
      test-while-idle: true
      time-between-eviction-runs-millis:  60000
      min-evictable-idle-time-millis: 100000複製代碼
  • 3.1.三、再寫個配置類加載數據源
@Configuration
@ConditionalOnClass(DruidDataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.alibaba.druid.pool.DruidDataSource", matchIfMissing = true)
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.druid")
    public DataSource dataSourceOne() {
        return DruidDataSourceBuilder.create().build();
    }
}複製代碼
  • 3.1.四、啓動效果:
2020-01-17 16:59:32.804  INFO 8520 --- [ main ] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
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
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
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]
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]
2020-01-17 16:59:32.932  INFO 8520 --- [ main ] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 18001 (http)
2020-01-17 16:59:32.943  INFO 8520 --- [ main ] c.j.mmzsblog.DatasourceTestApplication   : Started DatasourceTestApplication in 8.328 seconds (JVM running for 10.941)複製代碼

3.二、SpringBoot2.0中引用Druid

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

  • 3.2.一、不須要排除默認配置的數據源,直接引入置Druid數據源
<!-- 引用阿里巴巴的druid數據源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.31</version>
        </dependency>複製代碼

  • 3.2.二、在.yml文件中配置的Druid數據源的相關信息同3.1.3同樣
  • 3.2.三、再寫個配置類加載數據源同3.1.3同樣
  • 3.2.四、啓動後你一樣能看到打印出相似的信息
Located MBean 'dataSourceOne': registering with JMX server as MBean [com.alibaba.druid.spring.boot.autoconfigure:name=dataSourceOne,type=DruidDataSourceWrapper]複製代碼

3.三、優秀在哪?

看了上面的使用,超級簡單又木有?

首先咱們看看druid官網給出的幾個傳統鏈接池之間的對比吧:從上表能夠看出,Druid鏈接池在性能、監控、診斷、安全、擴展性這些方面遠遠超出競品。

官網是這樣介紹它的:

Druid鏈接池是阿里巴巴開源的數據庫鏈接池項目。Druid鏈接池爲監控而生,內置強大的監控功能,監控特性不影響性能。功能強大,能防SQL注入,內置Loging能診斷Hack應用行爲。

因此,小編我倒騰了這麼久,想明白了一件事,我之後仍是用阿里爸爸的Druid鏈接池吧,接入簡單,還自帶監控,而且它但是通過阿里巴巴各大系統考驗過的產品,值得信賴,省事省心啊。

參考:

  • 1:HikariCP的優勢:https://www.jianshu.com/p/129efe2c8e49
  • 二、druid官網:https://github.com/alibaba/druid/

歡迎關注公衆號:Java學習之道

我的博客網站:www.mmzsblog.cn

相關文章
相關標籤/搜索