連接池的實現
阿新 • • 發佈:2018-09-15
init true strong map lock 可能 實施 避免 ret 。
1. 背景
工程架構中有很多訪問下遊的需求,下遊包括但不限於服務/數據庫/緩存,其通訊步驟為:
(1)與下遊建立一個連接
(2)通過這個連接,收發請求
(3)交互結束,關閉連接,釋放資源
2. 為什麽需要連接池?
當並發量很低的時候,建立連接和關閉連接的過程是沒問題的,但當服務單機QPS達到幾百、幾千的時候,建立連接和銷毀連接就會成為瓶頸,此時如何優化?
結論很簡單,服務啟動的時候,先建立好若幹連接Array[Connection],但有請求過來的時候,從Array中取出一個,執行下遊操作,執行完再放回,從而避免反復的建立和銷毀連接,以提升性能。
而這個對Array[Connection]進行維護的數據結構,就是連接池
3. 連接池核心接口和實現
通過上面的討論,可以看到連接池ConnectionPool主要有三個核心接口:
(1)Init:初始化好Array[Connection],這個接口只在服務啟動時調用一次;
(2)GetConnection:請求每次需要訪問數據庫時,不是connect一個連接,而是通過連接池的這個接口拿連接;
(3)FreeConnection:請求每次訪問完數據庫時,不是關閉一個連接,而是把這個連接放回連接池。
連接池核心數據結構:
(1)連接數據Array[Connection]
(2)互斥鎖數組Array lock[N]
連接池核心接口實現:
Init() { for i = 1 to N { Array Connection [i] = new(); Array Connection [i]->connect(); Array lock[i] = 0; } } 說明:把所有連接和互斥鎖初始化 GetConnection() for i = 1 to N { if(Array lock[i] == 0) { Array lock[i] = 1; return Array Connection[i]; } } } 說明:找一個可用的連接,鎖住,並返回連接 FreeConnection(c) for i = 1 to N { if(Array Connection [i] == c) { Array lock[i] = 0; } } } 說明:找到連接,把鎖釋放
4. 細節
(1)如果連接全部被占用,是返回失敗,還是讓上遊等待?
(2)需要實施連接可用性檢測;
(3)為了讓調用方更友好,可能還需要包裝一層DAO層,讓“連接”對調用方都是黑盒的;
(4)通過freeArray,connectionMap可以讓取連接和放回連接都達到O(1)時間復雜度;
(5)可以通過hash實現id串行化;
(6)負載均衡、故障轉移、服務自動擴容都可以在這一層實現。
連接池的實現