日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

设计一个具有等待队列的连接池

發布時間:2023/12/4 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设计一个具有等待队列的连接池 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

????????說到連接池相關很多人都使用過,常見的有數據連接池,HttpClient連接池等。連接池的作用是保持一定量的連接讓交互過程復用這些連接,從而大大節省連接創建過程或過多的損耗。在連接池策略中往往當池沒有連接的情況都會拋出異常告訴使用者資源無法使用,正常來說這種做法比較普遍,但并發峰值往往都是瞬間存在的,只要沒資源就拒絕這種情況服務上或多或少有些不太友好。

應用需求

????????在構建組件網關轉發和HttpClient設計中大量加入了連接池,在最開始的設計中只要連接池的連接沒有的情況下直接拋出異常拒絕;但實際并發時的峰值往往是瞬間出現,在下一刻就會回落到比較低的水平;在這么短暫的時間內拒絕當前請求的確是沒有必要,因此在連接池前置加個等待隊列。

設計

????????針對等待設計一般兩種情況:一種是自旋等待,而另一種則是回調;前者不用說比較占用cpu資源,但好處就是代碼結構好;后者則cpu資源利用好,但基于異步回調函數方式代碼結構并不友好,集成邏輯比較麻煩。但在.net集成了async/await功能后異步處理再也不需要通訊函數回調的方式編寫,整體代碼結構和自旋等待方式并沒差異。

實現

????????接下來講述BeetleX.Http.Clients是如何實現具有等待隊列的連接池的,從而通過這機制保障并發峰值時可以接管更多的請求。針對連接池主要提供兩個方法分別是Pop和Push,前者是從池中獲取連接,后者則是把連接回收到池里.等待隊列基本就圍繞著這兩個方法處理即可。接下來看一下BeetleX.Http.Clients的HttpClientHandlerPool是怎樣實現的。

  • Pop

????????該方法是從連接池中獲取連接

public Task<HttpClientHandler> Pop() {lock (this){if (mPools.Count > 0){var result = mPools.Pop();result.Using = true;result.TimeOut = BeetleX.TimeWatch.GetElapsedMilliseconds() + TimeOut;return Task.FromResult(result);}if (Clients.Count < MaxConnections){var result = Create();result.Using = true;result.TimeOut = BeetleX.TimeWatch.GetElapsedMilliseconds() + TimeOut;return Task.FromResult(result);}if (mWaitQueue.Count < MaxWaitLength){TaskCompletionSource<HttpClientHandler> completionSource = new TaskCompletionSource<HttpClientHandler>();mWaitQueue.Enqueue(completionSource);return completionSource.Task;}else{throw new HttpClientException($"Request {Host} connections limit");}} }
  • 第一步是判斷連接池有沒有連接,如果有則直接返回可用連接。

  • 第二步如果連接池沒有連接,則判斷創建的連接數是否超過最大值,如果沒有則創建一個新的連接并返回。

  • 第三步判斷當前等待隊列是否超出最大值,如果不是則創建對應的TaskCompletionSource存儲到隊列中返回相應的Task對象。

  • Push

    由于涉及到等待隊列問題,所以當連接回收的時候也要做特別的處理

public void Push(HttpClientHandler client) {TaskCompletionSource<HttpClientHandler> result = null;lock (this){if (mWaitQueue.Count > 0){result = mWaitQueue.Dequeue();client.Using = true;client.TimeOut = BeetleX.TimeWatch.GetElapsedMilliseconds() + TimeOut;}else{client.Using = false;mPools.Push(client);}}if (result != null){Task.Run(() => result.SetResult(client));} }

????當連接回收后需要判斷一下是否存在隊列,如果存在則獲取隊列中等待的TaskCompletionSource并設置返回值;這里為何通過Task.Run來調用呢?主要原因是希望啟用新線程來回調,不讓當前線程處理回調任務影響其后續的工作。

使用

????針對連接池的使用只需要在調用Pop時加個await即可

client?=?await?HttpHost.Pool.Pop(); 【BeetleX通訊框架代碼詳解】 BeetleX

開源跨平臺通訊框架(支持TLS)
輕松實現高性能:tcp、http、websocket、redis、rpc和網關等服務應用

https://beetlex.io

如果你想了解某方面的知識或文章可以把想法發送到

henryfan@msn.com|admin@beetlex.io

總結

以上是生活随笔為你收集整理的设计一个具有等待队列的连接池的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。