最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Hikari?數(shù)據(jù)庫連接池內(nèi)部源碼實現(xiàn)的小細(xì)節(jié)

 更新時間:2023年02月17日 10:00:09   作者:brucelwl  
這篇文章主要介紹了Hikari?數(shù)據(jù)庫連接池內(nèi)部源碼實現(xiàn)的小細(xì)節(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Hikari 默認(rèn)幾個超時配置

連接創(chuàng)建超時時間 30s 

private static final long CONNECTION_TIMEOUT = SECONDS.toMillis(30);

連接存活驗證時間5s,這個時間就是驗證時socketTimeout,驗證之后恢復(fù)為0,

但是真正做數(shù)據(jù)查詢時默認(rèn)為0,表示永不超時

private static final long VALIDATION_TIMEOUT = SECONDS.toMillis(5);

連接空閑時間10分鐘

private static final long IDLE_TIMEOUT = MINUTES.toMillis(10);

連接最大存活時間30分鐘

private static final long MAX_LIFETIME = MINUTES.toMillis(30);

Hikari 連接池中默認(rèn)連接數(shù)量為10

默認(rèn)最小連接數(shù)等于最大相同未為10

private static final int DEFAULT_POOL_SIZE = 10;

Hikari通過CopyOnWriteArrayList保存所有的連接

com.zaxxer.hikari.util.ConcurrentBag#sharedList

線程無法獲取連接時通過SynchronousQueue實現(xiàn)公平阻塞等待

當(dāng)池的連接被用盡,Hikari通過SynchronousQueue實現(xiàn)讓線程阻塞等待,并且采用的是公平鎖。

源碼見com.zaxxer.hikari.util.ConcurrentBag#handoffQueue以及com.zaxxer.hikari.util.ConcurrentBag#ConcurrentBag構(gòu)造方法

Hikari內(nèi)部有三個單線程的 線程池 對象

  • houseKeepingExecutorService ,addConnectionExecutor,closeConnectionExecutor 分別是都只有一條線程的線程池,源碼見:com.zaxxer.hikari.pool.HikariPool。
  • houseKeepingExecutorService是一個ScheduledExecutorService對象。池中每創(chuàng)建一個連接,就會被封裝成一個PoolEntry對象,然后放在定時任務(wù)中,定時時間就是設(shè)置的max-lifetime。只要到達這個時間就會采取軟驅(qū)逐的方式從池中移除。
  • 除此之外,houseKeepingExecutorService還用于每隔30s來檢查一次池中的空閑連接、最大連接情況,并通過調(diào)用異步創(chuàng)建連接、異步銷毀連接的方法來維護池中連接數(shù)的平衡。

何謂軟驅(qū)逐

  • 如果這個連接正在被使用,則不立即關(guān)閉連接,但是通過PoolEntry對象中的private volatile boolean evict;字段來標(biāo)記為需要關(guān)閉。下次有線程來獲取到這個連接時,發(fā)現(xiàn)evict=true則調(diào)用異步關(guān)閉方法。重新獲取池中其它的連接。
  • 如果這個連接未被使用,則立即調(diào)用異步關(guān)閉連接的方法。

池中連接的創(chuàng)建,關(guān)閉,除了初始化時只同步創(chuàng)建1條,其它都是異步的。

  • 創(chuàng)建連接通過addConnectionExecutor(ThreadPoolExecutor)來完成,關(guān)閉連接通過closeConnectionExecutor(ThreadPoolExecutor)來完成.
  • 這兩個線程池都每個都只有一個線程。加上houseKeepingExecutorService,那么一個Hikari連接池會創(chuàng)建3條線程?。?!
  • 可以通過啟動參數(shù)-Dcom.zaxxer.hikari.blockUntilFilledInitializationFailTimeout單位ms,來讓Hikari啟動時等待創(chuàng)建完成設(shè)置的最小連接數(shù)。默認(rèn)為false

一個connection本質(zhì)上就是一個socket連接

一個連接池中,有多少個connection連接則對應(yīng)多少個 socket 對象與服務(wù)端的連接。

Hikari中會使用ThreadLocal來將連接綁定到線程

Hikari為了提高從池中獲取連接的性能,通過ThreadLocal來避免資源競爭,一個connection可以對應(yīng)多個Thread,一個Thread可以綁定多個connection,源碼見ConcurrentBag類中的成員變量private final ThreadLocal<List<Object>> threadList;

為什么ThreadLocal里面的泛型是List< Object >?

因為一個connection可以在不同時期被多個線程使用,當(dāng)另一個線程綁定的connection正在被別的線程使用時,就需要選擇其它沒有被使用的connection,新選擇的connection同樣需要綁定到這條線程,所以使用的是List來保存。

源碼見:com.zaxxer.hikari.util.ConcurrentBag#borrow

什么時候向ThreadLocal里面保存connection?

當(dāng)調(diào)用連接池中connection釋放資源的時候回收,這里的connection實際上是Hikari實現(xiàn)的一個代理類(ProxyConnection),封裝了JDBC 連接。

源碼見:com.zaxxer.hikari.pool.ProxyConnection#close

Hikari如何做到連接的回收

通過ProxyConnection代理類來實現(xiàn)。

源碼見:com.zaxxer.hikari.pool.ProxyConnection#close

Hikari通過CAS樂觀鎖來控制連接當(dāng)前狀態(tài)

Hikari通過PoolEntry來封裝Connection,并通過private volatile int state來記錄Connection當(dāng)前狀態(tài),主要有如下幾個枚舉值,并通過CAS樂觀鎖來維護這些狀態(tài),提高多線程之間獲取連接的性能.

public interface IConcurrentBagEntry{
  int STATE_NOT_IN_USE = 0;
  int STATE_IN_USE = 1;
  int STATE_REMOVED = -1;
  int STATE_RESERVED = -2;

  boolean compareAndSet(int expectState, int newState);
  void setState(int newState);
  int getState();
}

獲取連接,對驗證連接可用性的優(yōu)化

每次從池中獲取連接后,先判斷連接最后訪問時間和當(dāng)前時間差,如果小于500ms,則直接認(rèn)為連接是可用的,避免向服務(wù)器發(fā)送驗證的sql語句,提高連接池性能。

源碼見:com.zaxxer.hikari.pool.HikariPool#getConnection(long hardTimeout)

 if (poolEntry.isMarkedEvicted() || (elapsedMillis(poolEntry.lastAccessed, now) > aliveBypassWindowMs && !isConnectionAlive(poolEntry.connection))) {
    closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);
    timeout = hardTimeout - elapsedMillis(startTime);
 }

否則需要驗證連接可用性:

如果配置了connection-test-query則使用配置sql驗證,否則使用數(shù)據(jù)庫驅(qū)動程序?qū)崿F(xiàn)的java.sql.Connection#isValid(int timeout)方法驗證。

源碼見:com.zaxxer.hikari.pool.PoolBase#isConnectionAlive。

如果連接不可用,會輸出警告日志

如果驗證連接可用性過程,連接因為數(shù)據(jù)庫wait_timeout超時被服務(wù)端關(guān)閉,或者網(wǎng)絡(luò)異常,則會出現(xiàn)如下警告日志,

Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@2e2ce118 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.

解決方案參考我的另一篇博客:Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl問題排查

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論

那坡县| 中西区| 河池市| 澄江县| 舒兰市| 桂林市| 新乡县| 新沂市| 长垣县| 互助| 许昌市| 新巴尔虎左旗| 成都市| 彰化市| 安徽省| 凤凰县| 梅州市| 宁夏| 四会市| 棋牌| 山丹县| 东至县| 梅河口市| 成武县| 高雄县| 铜陵市| 交城县| 镇宁| 申扎县| 甘洛县| 山东省| 体育| 铜梁县| 建昌县| 洛川县| 驻马店市| 东方市| 邛崃市| 达拉特旗| 井陉县| 磴口县|