天天看點

KA,連接配接池居然這麼簡單?

《“ID串行化”保證群消息順序性》提到,可以通過連接配接池的改造,實作ID串行化,本篇講講連接配接池的原理,以及實作細節。

通常如何通過連接配接通路下遊?

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

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

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

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

不管是服務/資料庫/緩存,官方會提供不同語言的Driver、Document、DemoCode來指導使用方建立連接配接與調用接口。

以MongoDB的C++官方DriverAPI為例:

DBClientConnection* c = new DBClientConnection();

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

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

c->close();

畫外音:建立連接配接、發送請求、關閉連接配接,都非常清晰。

KA,連接配接池居然這麼簡單?

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

為什麼需要連接配接池?

當并發量很低的時候,連接配接可以臨時建立,但當服務吞吐量達到幾百、幾千的時候,建立連接配接connect和銷毀連接配接close就會成為瓶頸,此時該如何優化呢?

(1)當服務啟動的時候,先建立好若幹連接配接Array[DBClientConnection];

(2)當請求到達的時候,再從Array中取出一個,執行下遊操作,執行完放回;

進而避免反複的建立和銷毀連接配接,以提升性能。

而這個對Array[DBClientConnection]進行維護的資料結構,就是連接配接池。

有了連接配接池之後,資料庫操作的僞代碼變為:

DBClientConnection* c = 

    ConnectionPool::GetConnection();

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()

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

   Array lock[i] = 1;

   return Array DBClientConnection[i];

   }

畫外音:找一個可用的連接配接,鎖住,并傳回連接配接。

FreeConnection(c)

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

   Array lock[i] = 0;

  }

畫外音:找到連接配接,把鎖釋放。

KA,連接配接池居然這麼簡單?

會發現,連接配接池管理核心并沒有想象的複雜。

除了核心代碼,連接配接池還需要考慮哪些因素呢?

(1)需要實施連接配接可用性檢測,如果有連接配接失效,需要重建連接配接;

(2)通過freeArray,connectionMap等資料結構,可以讓取出連接配接和放回連接配接都達到O(1)時間複雜度;

(3)可以通過hash取連接配接,實作id串行化;

(4)每條連接配接被取到的機率必須相同,以實作負載均衡;

(5)如果有下遊故障,失效連接配接必須剔除,以實作故障自動轉移;

(6)如果有下遊新增,需要動态擴充連接配接池,以實作服務自動發現;

思路比結論更重要,希望大家有收獲。

本文轉自“架構師之路”公衆号,58沈劍提供。