天天看點

連接配接池原來這麼簡單(一分鐘系列)

應網友要求,寫一寫連接配接池實作細節。

一、如何通過連接配接通路下遊

工程架構中有很多通路下遊的需求,下遊包括但不限于服務/資料庫/緩存,其通訊步驟是為:

(1)與下遊建立一個連接配接

(2)通過這個連接配接,收發請求

(3)互動結束,關閉連接配接,釋放資源

這個連接配接是什麼呢,通過連接配接怎麼調用下遊接口?服務/資料庫/緩存,官方會提供不同語言的Driver、Document、DemoCode來教使用方建立連接配接與調用接口,以MongoDB的C++官方Driver API為例(僞代碼):

DBClientConnection* c = new DBClientConnection();

c->connect(“127.0.0.1:8888”);

c->insert(“db.s”, BSON(”shenjian”));

c->close();

這個DBClientConnection就是一個與MongoDB的連接配接,官方Driver通過它提供了若幹API,讓使用者可以對MongoDB進行連接配接,增删查改,關閉的操作,進而實作不同的業務邏輯。

二、為什麼需要連接配接池

當并發量很低的時候,上述僞代碼沒有任何問題,但當服務單機QPS達到幾百、幾千的時候,建立連接配接connect和銷毀連接配接close就會成為瓶頸,此時該如何優化?

結論也很簡單,服務啟動的時候,先建立好若幹連接配接Array[DBClientConnection],當有請求過來的時候,從Array中取出一個,執行下遊操作,執行完再放回,進而避免反複的建立和銷毀連接配接,以提升性能。

而這個對Array[DBClientConnection]進行維護的資料結構,就是連接配接池。有了連接配接池之後,資料庫操作的僞代碼變為:

DBClientConnection* c = ConnectionPool::GetConnection();

c->insert(“db.s”, BSON(”shenjian”));

ConnectionPool::FreeConnection(c);           
連接配接池原來這麼簡單(一分鐘系列)

三、連接配接池核心接口與實作

通過上面的讨論,可以看到連接配接池ConnectionPool主要有三個核心接口:

(1)Init:初始化好Array[DBClientConnection],這個接口隻在服務啟動時調用一次

(2)GetConnection:請求每次需要通路資料庫時,不是connect一個連接配接,而是通過連接配接池的這個接口來拿

(3)FreeConnection:請求每次通路完資料庫時,不是close一個連接配接,而是把這個連接配接放回連接配接池

連接配接池核心資料結構:

(1)連接配接數組Array DBClientConnection [N]

(2)互斥鎖數組Array lock[N]

連接配接池核心接口實作:

Init(){

 for i = 1 to N {

  Array DBClientConnection [i] = new();

  Array DBClientConnection [i]->connect();

  Array lock[i] = 0;

 }

}           

說明:把所有連接配接和互斥鎖初始化

GetConnection()

 for i = 1 to N {

  if(Array lock[i] == 0){

   Array lock[i] = 1;

   return Array DBClientConnection[i];

   }

 }

}           

說明:找一個可用的連接配接,鎖住,并傳回連接配接

FreeConnection(c)

 for i = 1 to N {

 if(Array DBClientConnection [i] == c){

   Array lock[i] = 0;

   }

  }

}           

說明:找到連接配接,把鎖釋放

連接配接池原來這麼簡單(一分鐘系列)

可以發現,簡單的連接配接池管理并不是很複雜,基本原理即如上所述。

四、未盡事宜

上述僞代碼忽略了一些細節,在實作連接配接池中是需要考慮的:

(1)如果連接配接全部被占用,是傳回失敗,還是讓上遊等待

(2)需要實施連接配接可用性檢測

(3)為了讓調用方更友好,可能還需要包裝一層DAO層,讓“連接配接”這個東西對調用方都是黑盒的

(4)通過freeArray,connectionMap可以讓取連接配接和放回連接配接都達到O(1)時間複雜度

(5)可以通過hash實作id串行化

(6)負載均衡、故障轉移、服務自動擴容都可以在這一層實作

希望這一分鐘大家有收獲。