泥瓦匠進階:鏈接池原理設計並不難

摘要: 原創出處 https://www.bysocket.com 「公衆號:泥瓦匠BYSocket 」歡迎關注和轉載,保留摘要,謝謝!

目錄java

  • 鏈接
  • 鏈接池產生緣由
  • 鏈接池實現原理
  • 小結

TEMPERANCE:Eat not to dullness;drink not to elevation.
節制:食不過飽,飲不過量。mysql

1、鏈接

什麼是鏈接?
鏈接,表明上游對下游的通訊或會話。好比客戶端鏈接服務器、服務器鏈接數據存儲等sql

鏈接其通訊的基本步驟,很相似 HTTP 操做:數組

  1. 上游對下游創建一個鏈接(客戶端與服務器須要創建鏈接。好比點擊某個超級連接)
  2. 上游經過鏈接,發送請求(創建鏈接後,客戶端發送請求給服務器)
  3. 上游經過鏈接,收到響應(服務器接到請求後,響應其響應信息)
  4. 上游關閉鏈接,釋放鏈接資源(客戶端接收服務器所返回的信息經過瀏覽器顯示在用戶的顯示屏上,而後客戶機與服務器斷開鏈接)

file

再深刻點,HTTP 持久鏈接是什麼?HTTP 持久鏈接是指用同一個 HTTP 底層的 TCP 鏈接來發送/接收多個 HTTP 請求/響應。擴展點,只須要在頭部設置:瀏覽器

Connection: Keep-Alive

爲何要有持久鏈接?每次都是從創建鏈接開始也能夠達到結果,而且最後是關閉鏈接釋放資源。這就是引出鏈接池產生緣由。服務器

2、鏈接池產生緣由

先看一下常見的 mysql-connector-java 包驅動下面 ConnectionImpl 源碼:微信

trackConnection()

execSQL()
commit()

close()

對 MySQL 多半是進行鏈接(connection),增刪改查並提交(execSQL、commit),關閉鏈接(close)操做,而後實現業務相關邏輯。其操做也很清晰:數據結構

  1. 創建鏈接
  2. 發送請求(數據的 CRUD 操做)
  3. 關閉鏈接

但,爲啥會須要有鏈接池?
其實在業務量流量不大,併發量也不大的狀況下,鏈接臨時創建徹底能夠。
但併發量起來,達到百級、千級,其中創建鏈接、關閉鏈接的操做會形成性能瓶頸,因此得考慮鏈接池來優化上述 1 和 3 操做:併發

  1. 取出鏈接(業務服務啓動時,初始化若干個鏈接,放在鏈接存儲中)
  2. 發送請求(當有請求,從鏈接存儲中中取出)
  3. 放回鏈接(執行完畢,鏈接放回鏈接存儲中)

這裏對鏈接存儲的數據結構,並維護鏈接,就是鏈接池。socket

3、鏈接池實現原理

鏈接池原理,能夠具體看下阿里巴巴 Druid 包的 DruidDataSource 源碼:

DruidConnectionHolder[] connections;

createConnection()
getConnection()
recycle()

鏈接池實現原理也不難,DruidDataSource 即德魯伊鏈接池,能夠核心設計接口:

  1. createConnection:服務啓動 init ,會建立一批指定數量的鏈接放入 connections 數組
  2. getConnection:這樣每次請求,不會新建一個鏈接。而是從 DruidConnectionHolder[] connections 數組中取出一個鏈接
  3. recycle:每次請求結束後,不是關閉鏈接,而是回收鏈接到 connections 數組

其中有個重入鎖 ReetrantLock,具體做用以下:

  • 獲取一個鏈接,鎖住
  • 返回該鏈接,使用鏈接
  • 使用完畢,回收鏈接,並釋放鎖

file

4、小結

核心鏈接池也就這麼點東西,具體還須要考慮其餘點以下:

  • 鏈接池鏈接設計遵照 LRU 策略,性能的關鍵點是鏈接是否 LRU 方式重用。LRU 資料:https://yq.aliyun.com/articles/70456
  • 經過 Hash 去鏈接,實現串行化
  • 能夠自動擴容鏈接數
  • 鏈接數過多,能夠自動關閉鏈接,釋放資源
  • 等等
  (關注微信公衆號,領取 Java 精選乾貨學習資料)
相關文章
相關標籤/搜索