04_連接池

在這裏插入圖片描述

在使用三方客戶端進行網絡通信時,我們首先要確定客戶端SDK是否是基於連接池技術實現的。我們知道,TCP是面向連接的基於字節流的協議:

  • 面向連接,意味着連接需要先創建再使用,創建連接的三次握手有一定開銷;
  • 基於字節流,意味着字節是發送數據的最小單元,TCP協議本身無法區分哪幾個字節是完整的消息體,也無法感知是否有多個客戶端在使
    用同一個TCP連接,TCP只是一個讀寫數據的管道

如果客戶端SDK沒有使用連接池,而直接是TCP連接,那麼就需要考慮每次建立TCP連接(3次握手)的開銷,並且因爲TCP基於字節流,在多線程的情況下對同一連接進行復用,可能會產生線程安全問題
在這裏插入圖片描述

我們先看一下涉及TCP連接的客戶端SDK,對外提供API的三種方式。在面對各種三方客戶端的時候,只有先識別出其屬於哪一種,才能理清楚
使用方式。
1,連接池和連接分離的API:有一個XXXPool類負責連接池實現,先從其獲得連接XXXConnection,然後用獲得的連接進行服務端請求,
完成後使用者需要歸還連接。通常,XXXPool是線程安全的,可以併發獲取和歸還連接,而XXXConnection是非線程安全的。對應到連
接池的結構示意圖中,XXXPool就是右邊連接池那個框,左邊的客戶端是我們自己的代碼。
2,內部帶有連接池的API:對外提供一個XXXClient類,通過這個類可以直接進行服務端請求;這個類內部維護了連接池,SDK使用者無需
考慮連接的獲取和歸還問題。一般而言,XXXClient是線程安全的。對應到連接池的結構示意圖中,整個API就是藍色框包裹的部分。
3,非連接池的API:一般命名爲XXXConnection,以區分其是基於連接池還是單連接的,而不建議命名爲XXXClient或直接是XXX。直接連
接方式的API基於單一連接,每次使用都需要創建和斷開連接,性能一般,且通常不是線程安全的。對應到連接池的結構示意圖中,這種
形式相當於沒有右邊連接池那個框,客戶端直接連接服務端創建連接。

1,如果是分離方式,那麼連接池本身一般是線程安全的,可以複用。每次使用需要從連接池獲取連接,使用後歸還,歸還的工作由使用者負
責。
2,如果是內置連接池,SDK會負責連接的獲取和歸還,使用的時候直接複用客戶端。
3,如果SDK沒有實現連接池(大多數中間件、數據庫的客戶端SDK都會支持連接池),那通常不是線程安全的,而且短連接的方式性能不會
很高,使用的時候需要考慮是否自己封裝一個連接池。

Jedis的API實現是我們說的三種類型中的第一種,也就是連接池和連接分離的API, JedisPool是線程安全的連接池,Jedis是非線程安全的單一連接。
而Apache HttpClient是內置連接池的API。

**連接池的配置不是一成不變的**
連接池提供了許多參數,包括最小(閒置)連接、最大連接、閒置連接生存時間、連接生存時間等。 其中,最重要的參數是最大連接數,它決定了連接池能使用的連接數量上限,達到上限後,新來的請求需要等待其他請求釋放連接。

最大連接數不是設置得越大越好。如果設置得太大,不僅僅是客戶端需要耗費過多的資源維護連接,更重要的是由於服務端對應的是多個客戶端,每一個客戶端都保持大量的連接,會給服務端帶來更大的壓力。這個壓力又不僅僅是內存力,可以想一下如果服務端的網絡模型是
一個TCP連接一個線程,那麼幾千個連接意味着幾千個線程,如此多的線程會造成大量的線程切換開銷。
當然,連接池最大連接數設置得太小,很可能會因爲獲取連接的等待時間太長,導致吞吐量低下,甚至超時無法獲取連接

數據庫設置最大連接數
在真實情況下,只要數據庫可以承受,你可以選擇在遇到連接超限的時候先設置一個足夠大的連接數,然後觀察最終應用的併發,再按照實際併發數留出一半的餘量來設置最終 的最大連接。
總結
對於使用姿勢其實就是兩點,一是確保連接池是複用的,二是儘可能在程序退出之前顯式關閉連接池釋放資源。連接池設計的初衷就是爲了保 持一定量的連接,這樣連接可以隨取隨用。從連接池獲取連接雖然很快,但連接池的初始化會比較慢,需要做一些管理模塊的初始化以及初始 最小閒置連接。一旦連接池不是複用的,那麼其性能會比隨時創建單一連接更差。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章