HikariCP源碼解析一創建數據庫連接池

一、HikariCP創建連接池的幾種方式

HikariCP是一個快速、簡單、可靠的JDBC連接池。大約130Kb,相比於其它流行的數據庫連接池非常的輕, spingboot2.0以及在國外非常有名的playFramework框架默認使用該連接池。

連接池 文件數 代碼行數
Vibur 34 1927
HikariCP 21 2218
Tomcat-JDBC 31 6345
BoneCP 49 7293
C3P0 120 1550

HikariCP提供了多種創建數據庫連接池的方式

硬編碼HikariConfig

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/simpsons");
config.setUsername("bart");
config.setPassword("51mp50n");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");

HikariDataSource ds = new HikariDataSource(config);

直接硬編碼HikariDataSource

HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/simpsons");
ds.setUsername("bart");
ds.setPassword("51mp50n");
...

加載properties文件

HikariConfig config = new HikariConfig("/some/path/hikari.properties");
HikariDataSource ds = new HikariDataSource(config);


example.properties

dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
dataSource.user=test
dataSource.password=test
dataSource.databaseName=mydb
dataSource.portNumber=5432
dataSource.serverName=localhost

HikariConfig是一個用來設置數據庫連接屬性屬性的普通java類。還給連接池設置了一些常用默認屬性:

private static final long CONNECTION_TIMEOUT = SECONDS.toMillis(30);
private static final long VALIDATION_TIMEOUT = SECONDS.toMillis(5);
private static final long IDLE_TIMEOUT = MINUTES.toMillis(10);
private static final long MAX_LIFETIME = MINUTES.toMillis(30);
private static final int DEFAULT_POOL_SIZE = 10;

值得說明的是HikariCP還可以使用系統的一個默認屬性:hikaricp.configurationFile

public HikariConfig() {
   dataSourceProperties = new Properties();
   healthCheckProperties = new Properties();

   minIdle = -1;
   maxPoolSize = -1;
   maxLifetime = MAX_LIFETIME;
   connectionTimeout = CONNECTION_TIMEOUT;
   validationTimeout = VALIDATION_TIMEOUT;
   idleTimeout = IDLE_TIMEOUT;
   initializationFailTimeout = 1;
   isAutoCommit = true;

   String systemProp = System.getProperty("hikaricp.configurationFile");
   if (systemProp != null) {
      loadProperties(systemProp);
   }
}

hikaricp.configurationFile,可用於指定屬性文件的位置。 如果您打算使用此選項,則使用默認構造函數構造HikariConfig或HikariDataSource實例,HikariCP會加載該值對應的屬性文件。

 

二、HikariCP獲取連接的getConnection方法

上篇介紹了HikariCP創建連接池的幾種方式,跟蹤源碼發現其真正創建連接池是在HikariDataSource裏的getConnection方法(即第一次獲取連接則去創建連接池)

private volatile HikariPool pool;
@Override
public Connection getConnection() throws SQLException{
   if (isClosed()) {
      throw new SQLException("HikariDataSource " + this + " has been closed.");
   }

   if (fastPathPool != null) {
      return fastPathPool.getConnection();
   }

   // See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
   HikariPool result = pool;
   if (result == null) {
      synchronized (this) {
         result = pool;
         if (result == null) {
            validate();
            LOGGER.info("{} - Starting...", getPoolName());
            try {
               pool = result = new HikariPool(this);
               this.seal();
            }
            catch (PoolInitializationException pie) {
               if (pie.getCause() instanceof SQLException) {
                  throw (SQLException) pie.getCause();
               }
               else {
                  throw pie;
               }
            }
            LOGGER.info("{} - Start completed.", getPoolName());
         }
      }
   }

   return result.getConnection();
}

這裏使用了雙重檢查機制,要注意的是pool變量使用了volatile這個關鍵字,原因是new一個對象並不是一個原子操作,要經過以下步驟:

  1. 給pool分配內存
  2. 調用構造函數初始化成員變量
  3. 將pool對象指向分配的內存(此步驟完成pool即爲非空)

沒有volatile關鍵字上面這3個步驟可能由於指令重排序令pool在多線程下未正確初始化即被使用則報錯。volatile可禁止指令重排序,並強制本地線程去主存中讀取pool變量。

 

 

三、hikari連接池屬性詳解

 

一、主要配置#

1、dataSourceClassName#

這是DataSourceJDBC驅動程序提供的類的名稱。請查閱您的特定JDBC驅動程序的文檔以獲取此類名稱,或參閱下表。注XA數據源不受支持。XA需要像bitronix這樣的真正的事務管理器 。請注意,如果您正在使用jdbcUrl“舊式”基於DriverManager的JDBC驅動程序配置,則不需要此屬性 。 默認值:無

2、jdbcUrl#

該屬性指示HikariCP使用“基於DriverManager的”配置。我們認爲基於DataSource的配置(上圖)由於各種原因(參見下文)是優越的,但對於許多部署來說,幾乎沒有顯着差異。 在“舊”驅動程序中使用此屬性時,您可能還需要設置該 driverClassName屬性,但不要先嚐試。 請注意,如果使用此屬性,您仍然可以使用DataSource屬性來配置您的驅動程序,實際上建議您使用URL本身中指定的驅動程序參數。 默認值:無

3、username#

此屬性設置從基礎驅動程序獲取連接時使用的默認身份驗證用戶名。請注意,對於DataSources,這通過調用DataSource.getConnection(username, password)基礎DataSource 以非常確定的方式工作。但是,對於基於驅動程序的配置,每個驅動程序都不同。在基於驅動程序的情況下,HikariCP將使用此username屬性來設置傳遞給驅動程序調用的user屬性。如果這不是你所需要的,例如完全跳過這個方法並且調用。 默認值:無PropertiesDriverManager.getConnection(jdbcUrl, props)addDataSourceProperty("username", ...)

4、password#

此屬性設置從基礎驅動程序獲取連接時使用的默認身份驗證密碼。請注意,對於DataSources,這通過調用DataSource.getConnection(username, password)基礎DataSource 以非常確定的方式工作。但是,對於基於驅動程序的配置,每個驅動程序都不同。在基於驅動程序的情況下,HikariCP將使用此password屬性來設置傳遞給驅動程序調用的password屬性。如果這不是你所需要的,例如完全跳過這個方法並且調用。 默認值:無

二、常用配置#

5、autoCommit#

此屬性控制從池返回的連接的默認自動提交行爲。它是一個布爾值。 默認值:true

6、 connectionTimeout#

此屬性控制客戶端(即您)將等待來自池的連接的最大毫秒數。如果在沒有可用連接的情況下超過此時間,則會拋出SQLException。最低可接受的連接超時時間爲250 ms。 默認值:30000(30秒)

7、 idleTimeout#

此屬性控制允許連接在池中閒置的最長時間。 此設置僅適用於minimumIdle定義爲小於maximumPoolSize。一旦池達到連接,空閒連接將不會退出minimumIdle。連接是否因閒置而退出,最大變化量爲+30秒,平均變化量爲+15秒。在超時之前,連接永遠不會退出。值爲0意味着空閒連接永遠不會從池中刪除。允許的最小值是10000ms(10秒)。 默認值:600000(10分鐘)

8、 maxLifetime#

此屬性控制池中連接的最大生存期。正在使用的連接永遠不會退休,只有在關閉後纔會被刪除。在逐個連接的基礎上,應用較小的負面衰減來避免池中的大量消失。 我們強烈建議設置此值,並且應該比任何數據庫或基礎設施規定的連接時間限制短几秒。 值爲0表示沒有最大壽命(無限壽命),當然是idleTimeout設定的主題。 默認值:1800000(30分鐘)

9、connectionTestQuery#

如果您的驅動程序支持JDBC4,我們強烈建議您不要設置此屬性。這是針對不支持JDBC4的“傳統”驅動程序Connection.isValid() API。這是在連接從池中獲得連接以確認與數據庫的連接仍然存在之前將要執行的查詢。再一次,嘗試運行沒有此屬性的池,如果您的驅動程序不符合JDBC4的要求,HikariCP將記錄一個錯誤以告知您。 默認值:無

10、minimumIdle#

該屬性控制HikariCP嘗試在池中維護的最小空閒連接數。如果空閒連接低於此值並且連接池中的總連接數少於此值maximumPoolSize,則HikariCP將盡最大努力快速高效地添加其他連接。但是,爲了獲得最佳性能和響應尖峯需求,我們建議不要設置此值,而是允許HikariCP充當固定大小的連接池。 默認值:與maximumPoolSize相同

11、maximumPoolSize#

此屬性控制池允許達到的最大大小,包括空閒和正在使用的連接。基本上這個值將決定到數據庫後端的最大實際連接數。對此的合理價值最好由您的執行環境決定。當池達到此大小並且沒有空閒連接可用時,對getConnection()的調用將connectionTimeout在超時前阻塞達幾毫秒。請閱讀關於游泳池尺寸。 默認值:10

12、metricRegistry#

該屬性僅通過編程配置或IoC容器可用。該屬性允許您指定池使用的Codahale / Dropwizard 實例MetricRegistry來記錄各種指標。有關 詳細信息,請參閱Metrics維基頁面。 默認值:無

13、healthCheckRegistry#

該屬性僅通過編程配置或IoC容器可用。該屬性允許您指定池使用的Codahale / Dropwizard 的實例HealthCheckRegistry來報告當前的健康信息。有關 詳細信息,請參閱健康檢查 wiki頁面。 默認值:無

14、poolName#

此屬性表示連接池的用戶定義名稱,主要出現在日誌記錄和JMX管理控制檯中以識別池和池配置。 默認:自動生成

三、不常用配置#

15、 initializationFailTimeout#

如果池無法成功初始化連接,則此屬性控制池是否將“快速失敗”。任何正數都取爲嘗試獲取初始連接的毫秒數; 應用程序線程將在此期間被阻止。如果在超時發生之前無法獲取連接,則會引發異常。此超時被應用後的connectionTimeout 期。如果值爲零(0),HikariCP將嘗試獲取並驗證連接。如果獲得連接但未通過驗證,將拋出異常並且池未啓動。但是,如果無法獲得連接,則會啓動該池,但後續獲取連接的操作可能會失敗。小於零的值將繞過任何初始連接嘗試,並且在嘗試獲取後臺連接時,池將立即啓動。因此,以後努力獲得連接可能會失敗。 默認值:1

16、isolateInternalQueries#

此屬性確定HikariCP是否在其自己的事務中隔離內部池查詢,例如連接活動測試。由於這些通常是隻讀查詢,因此很少有必要將它們封裝在自己的事務中。該屬性僅適用於autoCommit禁用的情況。 默認值:false

17、allowPoolSuspension#

該屬性控制池是否可以通過JMX暫停和恢復。這對於某些故障轉移自動化方案很有用。當池被暫停時,呼叫 getConnection()將不會超時,並將一直保持到池恢復爲止。 默認值:false

18、readOnly#

此屬性控制默認情況下從池中獲取的連接是否處於只讀模式。注意某些數據庫不支持只讀模式的概念,而其他數據庫則在Connection設置爲只讀時提供查詢優化。無論您是否需要此屬性,都將主要取決於您的應用程序和數據庫。 默認值:false

19、registerMbeans#

該屬性控制是否註冊JMX管理Bean(“MBeans”)。 默認值:false

20、catalog#

該屬性設置默認目錄爲支持目錄的概念數據庫。如果未指定此屬性,則使用由JDBC驅動程序定義的默認目錄。 默認:驅動程序默認

21、connectionInitSql#

該屬性設置一個SQL語句,在將每個新連接創建後,將其添加到池中之前執行該語句。如果這個SQL無效或引發異常,它將被視爲連接失敗並且將遵循標準重試邏輯。 默認值:無

22、driverClassName#

HikariCP將嘗試通過DriverManager僅基於驅動程序來解析驅動程序jdbcUrl,但對於一些較舊的驅動程序,driverClassName還必須指定它。除非您收到明顯的錯誤消息,指出找不到驅動程序,否則請忽略此屬性。 默認值:無

23、transactionIsolation#

此屬性控制從池返回的連接的默認事務隔離級別。如果未指定此屬性,則使用由JDBC驅動程序定義的默認事務隔離級別。如果您有針對所有查詢通用的特定隔離要求,請僅使用此屬性。此屬性的值是從不斷的名稱Connection 類,如TRANSACTION_READ_COMMITTED,TRANSACTION_REPEATABLE_READ等 默認值:驅動程序默認

24、 validationTimeout#

此屬性控制連接測試活動的最長時間。這個值必須小於connectionTimeout。最低可接受的驗證超時時間爲250 ms。 默認值:5000

25、 leakDetectionThreshold#

此屬性控制在記錄消息之前連接可能離開池的時間量,表明可能存在連接泄漏。值爲0意味着泄漏檢測被禁用。啓用泄漏檢測的最低可接受值爲2000(2秒)。 默認值:0

26、 dataSource#

此屬性僅通過編程配置或IoC容器可用。這個屬性允許你直接設置DataSource池的實例,而不是讓HikariCP通過反射來構造它。這在一些依賴注入框架中可能很有用。當指定此屬性時,dataSourceClassName屬性和所有DataSource特定的屬性將被忽略。 默認值:無

27、schema#

該屬性設置的默認模式爲支持模式的概念數據庫。如果未指定此屬性,則使用由JDBC驅動程序定義的默認模式。 默認:驅動程序默認

28、 threadFactory#

此屬性僅通過編程配置或IoC容器可用。該屬性允許您設置java.util.concurrent.ThreadFactory將用於創建池使用的所有線程的實例。在一些只能通過ThreadFactory應用程序容器提供的線程創建線程的有限執行環境中需要它。 默認值:無

29、 scheduledExecutor#

此屬性僅通過編程配置或IoC容器可用。該屬性允許您設置java.util.concurrent.ScheduledExecutorService將用於各種內部計劃任務的實例。如果爲ScheduledThreadPoolExecutor 實例提供HikariCP,建議setRemoveOnCancelPolicy(true)使用它。 默認值:無

 

http://www.longhuashen.com/2018/04/14/hikaricp-01/

http://www.longhuashen.com/2018/04/14/hikaricp-02/

https://www.cnblogs.com/CodingJacob/p/12052893.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章