原文:
https://gitlib.com/page/link-pool.html
在了解連接池之前,我們需要對長、短鏈接建立初步認識。我們都知道,網絡通信大部分都是基于TCP/IP協議,數據傳輸之前,雙方通過“三次握手”建立連接,當數據傳輸完成之后,又通過“四次揮手”釋放連接,以下是“三次握手”與“四次揮手”示意圖:
三次握手建立連接示意圖:
四次揮手釋放連接示意圖:
長、短連接
長、短連接是相對通信時間而言的。長連接相對短連接而言,多了一個保持連接的過程,可以在一個連接上可以連續發送多個數據包,在連接保持期間,如果沒有數據包發送,需要雙方發鏈路檢測包。
短連接
短連接的操作步驟是:
建立連接——數據傳輸——關閉連接…建立連接——數據傳輸——關閉連接
client向server發起連接請求,server接到請求,然后雙方建立連接。client向server發送消息,server回應client,然后一次請求就完成了。這時候雙方任意都可以發起close操作,不過一般都是client先發起close操作。上述可知,短連接一般只會在 client/server間傳遞一次請求操作。
短連接的優點是:管理起來比較簡單,存在的連接都是有用的連接,不需要額外的控制手段。
長連接
長連接的操作步驟是:
建立連接——數據傳輸…(保持連接)…數據傳輸——關閉連接
client向server發起連接,server接受client連接,雙方建立連接,client與server完成一次請求后,它們之間的連接并不會主動關閉,后續的讀寫操作會繼續使用這個連接。
TCP長連接保持的兩種辦法:
- 應用層面的心跳機制
自定義心跳消息頭.,一般客戶端主動發送到服務端,服務器接收后進行回應(也可以不回應),以便能夠偵測連接是否異常斷開。
- TCP協議自帶的保活功能
通過設置TCP keepalive的屬性,并設置發送底層心跳包的時間間隔。TCP keepalive是在底層定時發送心跳報文,服務器端接收到底層的心跳報文直接丟棄,不關心其內容。
長、短連接總結
- 長連接可以省去較多的TCP建立和關閉的操作,減少浪費,節約時間;
- 長連接需要進行鏈接存活探測;
- 短連接對于服務器來說管理較為簡單,存在的連接都是有用的連接,不需要額外的控制手段;
- 短連接如果請求頻繁,將在TCP的建立和關閉操作上浪費時間和帶寬;
HTTP協議
HTTP協議是無狀態的,在HTTP/1.0中默認使用短連接,客戶端和服務器每進行一次HTTP操作,瀏覽器就會重新建立一個HTTP會話。
而從HTTP/1.1起,默認使用長連接,用以保持連接特性,使用長連接的HTTP協議,會在響應頭加入這行代碼:
Connection:keep-alive
在使用長連接的情況下,當一個網頁打開完成后,客戶端和服務器之間用于傳輸HTTP數據的TCP連接不會關閉,客戶端再次訪問這個服務器時,會繼續使用這一條已經建立的連接。Keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的服務器軟件中設定這個時間。實現長連接需要客戶端和服務端都支持長連接。
HTTP協議的長連接和短連接,實質上是TCP協議的長連接和短連接。
連接池
基于TCP/IP協議,我們可以知道,頻繁的連接創建和銷毀都需要消耗資源,而連接池是將已經創建好的連接保存在池中,當有請求來時,直接使用已經創建好的連接進行訪問,這樣省略了創建連接和銷毀連接的過程。這樣性能上得到了提高。
以數據庫連接池為例,基本原理如下:
- 建立數據庫連接池對象;
- 按照事先指定的參數創建初始數量的數據庫連接;
- 對于一個數據庫訪問請求,直接從連接池中得到一個連接,如果數據庫連接池對象中沒有空閑的連接,且連接數沒有達到最大(即:最大活躍連接數),創建一個新的數據庫連接;
- 關閉數據庫連接,將連接放入空閑隊列中,如實際空閑連接數大于初始空閑連接數則釋放連接;
- 釋放數據庫連接池對象,并釋放所有連接;
連接池技術帶來的好處:
- 資源重用
由于連接得到重用,避免了頻繁創建、釋放連接引起的大量性能開銷。在減少系統消耗的基礎上,另一方面也增進了系統運行環境的平穩性(減少內存碎片以及臨時進程/線程的數量)。
- 更快的系統響應速度
連接池在初始化過程中,往往已經創建了若干連接置于池中備用。此時連接的初始化工作均已完成。對于業務請求處理而言,直接利用現有可用連接,避免了連接初始化和釋放過程的時間開銷,從而縮減了系統整體響應時間。
- 統一的連接管理,避免連接泄漏
在較為完備的連接池實現中,可根據預先的連接占用超時設定,強制收回被占用連接。從而避免了常規連接操作中可能出現的資源泄漏。
常見連接池實現
以php開發為例,基于PHP-FPM機制實現的Web服務,并不容易實現連接池,而常駐內存的開發框架,例如workerman、swoole 則可以簡單實現連接池功能。PHP-FPM機制下的連接池需要借助第三方Proxy實現,例如:
- php-cp:國內大神寫的php第三方擴展,支持PDO與redis連接池,完美集成主流PHP開發框架;
- SMProxy:一個基于 MySQL 協議,Swoole 開發的MySQL數據庫連接池;