设计一个具有等待队列的连接池
????????說到連接池相關很多人都使用過,常見的有數據連接池,HttpClient連接池等。連接池的作用是保持一定量的連接讓交互過程復用這些連接,從而大大節省連接創建過程或過多的損耗。在連接池策略中往往當池沒有連接的情況都會拋出異常告訴使用者資源無法使用,正常來說這種做法比較普遍,但并發峰值往往都是瞬間存在的,只要沒資源就拒絕這種情況服務上或多或少有些不太友好。
應用需求
????????在構建組件網關轉發和HttpClient設計中大量加入了連接池,在最開始的設計中只要連接池的連接沒有的情況下直接拋出異常拒絕;但實際并發時的峰值往往是瞬間出現,在下一刻就會回落到比較低的水平;在這么短暫的時間內拒絕當前請求的確是沒有必要,因此在連接池前置加個等待隊列。
設計
????????針對等待設計一般兩種情況:一種是自旋等待,而另一種則是回調;前者不用說比較占用cpu資源,但好處就是代碼結構好;后者則cpu資源利用好,但基于異步回調函數方式代碼結構并不友好,集成邏輯比較麻煩。但在.net集成了async/await功能后異步處理再也不需要通訊函數回調的方式編寫,整體代碼結構和自旋等待方式并沒差異。
實現
????????接下來講述BeetleX.Http.Clients是如何實現具有等待隊列的連接池的,從而通過這機制保障并發峰值時可以接管更多的請求。針對連接池主要提供兩個方法分別是Pop和Push,前者是從池中獲取連接,后者則是把連接回收到池里.等待隊列基本就圍繞著這兩個方法處理即可。接下來看一下BeetleX.Http.Clients的HttpClientHandlerPool是怎樣實現的。
Pop
????????該方法是從連接池中獲取連接
第一步是判斷連接池有沒有連接,如果有則直接返回可用連接。
第二步如果連接池沒有連接,則判斷創建的連接數是否超過最大值,如果沒有則創建一個新的連接并返回。
第三步判斷當前等待隊列是否超出最大值,如果不是則創建對應的TaskCompletionSource存儲到隊列中返回相應的Task對象。
Push
由于涉及到等待隊列問題,所以當連接回收的時候也要做特別的處理
????當連接回收后需要判斷一下是否存在隊列,如果存在則獲取隊列中等待的TaskCompletionSource并設置返回值;這里為何通過Task.Run來調用呢?主要原因是希望啟用新線程來回調,不讓當前線程處理回調任務影響其后續的工作。
使用
????針對連接池的使用只需要在調用Pop時加個await即可
開源跨平臺通訊框架(支持TLS)
輕松實現高性能:tcp、http、websocket、redis、rpc和網關等服務應用
https://beetlex.io
如果你想了解某方面的知識或文章可以把想法發送到
henryfan@msn.com|admin@beetlex.io
總結
以上是生活随笔為你收集整理的设计一个具有等待队列的连接池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF MVVM 弹框之等待框
- 下一篇: 你不该错过的2020中国开源年报,填开源