.netcore使用SocketAsyncEventArgs Pool需要注意!
在.net中做網路通訊往往都會用到SocketAsyncEventArgs
,為了得到更好的效能配合Pool複用SocketAsyncEventArgs
可以得到一個更好的效果,但在dotnet core在linux下這一塊的處理好像存在嚴重的問題
!經過多天的測試,終於在Linux下Debug到這一情況,實時除錯輸出接收的資料並不是當前請求的資料,而是之前另一請求的資料…… 接下來一下問題的實際情況!
問題的初現
前段時間有一個使用者說FastHttpApi
跑了一段時間後就出現請求混亂的情況,使用者反映測試都正常,一發布上線在叢集環境下執行一段時間後就會出現這情況……然後自己也根據相應的叢集情況搭了個測試環境壓測了一段時間也沒出現這情況。本以為是使用者叢集路由轉發的一些特性引起的異常就放下了這問題繼續完成新功能版本。
再次發現問題並確認
當元件的介面叢集呼叫體功能完成後,開始做介面混合呼叫併發測試,這個時候出現一些怪異的情況,當前請求返回的資料並不是當前請求資料內容,而是來源於其他請求的資料內容!後來在測試的過程中同時用瀏覽器訪問相關介面,這個時候問題再一次出現,瀏覽器得到響應的資料並不是請求響應的資料,而是測試介面那邊的資料。後來關閉壓力測試,單獨用瀏覽器訪問還是有異常,開啟日誌發現瀏覽器請求的資料到服務端接收得到的資料竟然是之前測試請求的資料!這樣的問題相當尷尬……因為接收資料是由‘’SocketAsyncEventArgs‘’來處理,我一直不相信問題出在SocketAsyncEventArgs
身上;最終迫於沒辦法的情況只能除錯Linux執行的程式碼,
從結果看接收的資料並不是瀏覽器發出請求的資料,而是之前測試程式請求的內容,資料顯示User-Agent都不是瀏覽器的內容。
調整實現
按理這樣的問題不應該出現,因為早期MSDN也是推薦使用SocketAsyncEventArgs
Pool的方式來複用SocketAsyncEventArgs
提高效能。asp.net core
核心的網路模組也是用這個的,如果有問題應該早就發現並解決掉!檢視KestrelHttpServer
SocketAsyncEventArgs
Pool,每個連線都是單獨的SocketAsyncEventArgs
並沒有通過Pool共享,對應用的一次繫結的Buffer已經改由Pipe統一管理,每次收發都重新設定一下Buffer屬性。 為了快速地解決這一問題,放棄了原有SocketAsyncEventArgs
Pool的使用方式,改用KestrelHttpServer
方式進行元件改造,這種方式通過了兩天的混合併發測試暫沒有出現之前的情況,估計之前的問題是由SocketAsyncEventArgs
共享複用導致的;則於無法判斷最終向corefx團隊提了:issue,https://github.com/dotnet/corefx/issues/33794 這問題應該是存在的,因為碰到這一情況還有其他人。
總結
這問題發現到排查花了一個多星期的時間……到底是SocketAsyncEventArgs
的bug還是使用上不對導致的還沒搞清楚,已經把相關問題描述和測試出現問題的程式提交給corefx團隊,希望儘快能搞清楚具體原因。通過這一次問題總結出一個問題,在做網路測試的時候需要做更多的混合驗證測試,特別針對這一問題,由於資料都是符合當前協議的,所以並不會有什麼異常出現。但導致資料混亂這種問題比異常來得更嚴重和影響面更大。