啊告组,這....小馬曾經也很好奇這是個什么玩意,后面寫GO的時候因為要自己實現(xiàn)DB層和redis層癌佩,才對它有了更進一步深入的了解木缝。但要是正兒八經地說呢,也不知道該怎么描述围辙。還是借助網絡上各路大神的文章來拋玉引我這個磚吧我碟。
一、什么是連接池
借用網文《如何實現(xiàn)一個連接池姚建?一文帶你深入淺出矫俺,徹底搞懂!》來說明吧掸冤,再次感謝作者厘托。
注意小馬加粗的文字部分。
“池”是一種非常形象化的描述贩虾,它是一種容器催烘,做儲存之用;在編程中我們往往使用數組缎罢、鏈表伊群、隊列考杉、map來表達。實現(xiàn)的代碼原理是比較好理解的舰始。
“連接”是網絡中用于傳輸數據的通道崇棠;“連接”才是我們要真正去使用的對象,而“池”是用來管理“多個連接”的一種方式丸卷。
如果沒有用“池”來統(tǒng)一管理“連接”枕稀,“連接”將散布在程序各處;那為了使用方便谜嫉,我們往往會在使用時建立連接萎坷,使用完畢后,就關閉連接沐兰。所以“連接池”給我們提供了使用“連接”的方便哆档。
同時,池是做儲存之用的住闯,所以“連接池”中的“連接”肯定是已經建立好的長連接瓜浸,比如tcp連接、websocket連接等比原,即取即用插佛,用完放回(池里存儲的實質是一堆已創(chuàng)建好的連接對象,參考這里)量窘。如果沒有真正理解“連接池”的本質雇寇,在面試中可能會出現(xiàn)“http連接池”的笑話!(但這里小馬有個疑問蚌铜,但是http的底層不是tcp嗎谢床,而且http從HTTP/1.1起,默認使用長連接了厘线,既然長連接為什么不能有連接池的概念?換句話說出革,只要是長連接是不是都可以搞連接池)
根據下游類型造壮,我們常見有數據庫連接池、緩存連接池骂束、服務連接池耳璧,如下圖所示:
在編程中,我們還經常會碰到進程池(記得小馬曾經有被問到swoole的進程模型展箱,進程池)旨枯、線程池、協(xié)程池混驰、內存池攀隔、對象池等皂贩。
二、為什么需要連接池
除了連接池能非常方便的對連接進行管理外昆汹,一句話明刷,在高吞吐時連接池大大提高了數據傳輸的效率。
從兩個方面說:
1满粗、避免反復的三次握手和四次握手
長連接的建立需要進行三次握手辈末,而連接的釋放需要進行四次握手,這是發(fā)生在系統(tǒng)層面的兩個動作映皆,對于單條連接來說耗時微乎其微挤聘,但在高吞吐場景時,耗時則不能忽略捅彻。
所以連接池的即取即用和用完放回的特性组去,避免了大量三次握手和四次握手的無效耗時,節(jié)省了系統(tǒng)資源沟饥。
2添怔、 增加并行車道,實現(xiàn)全雙工并行贤旷,提高QPS
數據通信包括單工广料、半雙工和全雙工。單工通信如下圖幼驶,數據只能從A到B艾杏,不符合訪問下游服務的場景。
半雙工通信如下圖盅藻,數據可以從A到B购桑,也可從B到A,但是同一時刻只能一個方向上進行數據傳輸氏淑,通道利用率是50%勃蜘。
全雙工通信如下圖,可同時存在從A到B和從B到A的數據傳輸假残,通道的利用率是100%缭贡。長連接就是全雙工通信。
在IO密集型的互聯(lián)網應用中辉懒,一條全雙工通信通道仍然無法滿足數據吞吐的需求時阳惹,該如何解決?
在互聯(lián)網性能測試指標中有這樣一個公式:
QPS(吞吐量) =?并發(fā)數 / 平均響應時間
在平均響應時間不變的情況下眶俩,適度增加并發(fā)數可以提升吞吐量莹汤;所以采用多條全雙工通信的方式可以在一定程度上(平均響應時間沒有大幅增加)提高吞吐量,而連接池則就最好的實現(xiàn)方式颠印。
總結一下:為什么需要連接池纲岭?
(1)方便管理連接抹竹;
(2)避免反復三次握手和四次握手;
(3)更好地實現(xiàn)全雙工并行荒勇。
三柒莉、如何實現(xiàn)一個連接池
該連接池的“池”通過隊列數據結構進行實現(xiàn),隊列先進先出的特性保證了使用連接的均衡性沽翔,每一條連接都可以均勻的被使用到兢孝。
連接池對外提供get()和free()兩個API,get()用于從隊首“出隊”獲取一條可用連接仅偎,free()用于將使用完的連接從對尾“入隊”釋放到隊列中跨蟹。
業(yè)務代碼在低峰時會降低get()動作,所以連接池中的連接在長時間不用時會導致失效橘沥,此時贝靶活線程在監(jiān)測到get()的使用頻率較低時,會模擬業(yè)務程序調用get()獲取連接后發(fā)送心跳包座咆,然后再通過free()將被绷∫眨活的連接放回隊列中,達到連接池中所有連接苯樘眨活的目的堤舒。
那么小馬的問題來了,我們平時使用的連接池lib哺呜,通常在連接使用完會調用一下close()函數舌缤,這個函數的真實動作是直接關閉連接嗎?
顯然根據本文的分析答案是否定的某残。
使用完后必須?con.close()?掉?国撵,使用連接池的話,執(zhí)行?con.close?并不會關閉與數據庫的?TCP?連接玻墅,而是將連接還回到池中去介牙,如果不?close?掉的話,這個連接將會一直被占用澳厢,直接連接池中的連接耗盡為止耻瑟。?
至于是如何做到?con.close?并不是真正意義上的關閉連接?而是直接將連接還回到池中去赏酥? 非本文中重點不贅述,參考這里谆构÷惴觯】
四、擴展知識:高級連接池
高級連接池通常應用在微服務系統(tǒng)中搬素,如下圖:連接池連接下游多個節(jié)點呵晨。
高級連接池具備這樣幾個特性:
1魏保、?高可用:下游任意一個server 宕機時,連接池會關閉相關無效連接摸屠,防止被client訪問谓罗;
2、?高可擴展:下游增加一個server節(jié)點時季二,連接池會發(fā)現(xiàn)并建立到新server節(jié)點的連接檩咱,供client訪問;
3胯舷、?負載均衡:連接池會根據下游server的服務能力的高低分配數據請求刻蚯;
4、?中間件:當下游server是類MySQL數據庫并分片時桑嘶,連接池會將請求打在相應的數據節(jié)點上炊汹,并對數據進行聚合。
小馬的疑問:微服務之間的PRC通信協(xié)議grpc也是需要處理連接池的嗎逃顶?好像沒有建立長連接吧讨便?本文中的高級連接是針對長連接的地方而言嗎?比如http2協(xié)議以政。
對于微服務用例霸褒,將HTTP / 1.1與HTTP / 2進行比較,通常HTTP / 1.1連接池要大得多(例如10倍) -50x)妙蔗,而不是HTTP / 2連接池傲霸,但出于上述原因,您仍然希望使用HTTP / 2連接池眉反。?
有待進一步探究...