簡體   English   中英

SocketAsyncEventArgs ReceiveAsync限制(未調用arg.Complete)

[英]SocketAsyncEventArgs ReceiveAsync Limitations (arg.Complete not called)

我們有一個相當標准的SocketAsyncEventArgs的TCP實現(與您可以在Google上搜索到的眾多示例沒有真正的區別)。

我們有一個負載測試控制台應用程序(也使用SocketAsyncEventArgs),每秒可發送x條消息。 我們使用線程旋轉在1000毫秒內引入大多數准確的間隔來發送消息(與盡快發送x消息然后等待剩余的1000毫秒相反)。

我們發送的消息大小約為2k,服務器實現通過預先分配的HTTP OK 200響應來響應(在同一套接字上)。

我們希望能夠使用SocketAsyncEventArgs每秒發送100條消息(如果不是1000條)。 我們發現,通過簡單地阻止TcpListener / TcpClient,我們可以處理〜150msg / s。 但是,即使在20秒內每秒僅發送50條消息,我們平均也會丟失1000條消息中的27條。

這是一個TCP實現,因此我們當然希望不會丟失任何消息。 特別是在吞吐量如此低的情況下。

我試圖避免粘貼整個實現(約250行),但是如果您認為有幫助,可以根據要求提供代碼。 我的問題是,SAEA應該給我們帶來什么負擔 假設我們為接受/接收/發送參數預先分配了單獨的池,我們已經確認這些池永遠不會餓死,為什么我們不為每個消息都收到arg.Complete回調呢?

注意:在執行過程中沒有看到套接字錯誤

對評論的回應

@usr:像您一樣,我們擔心我們的實現可能會遇到嚴重問題。要確認這一點,我們從這個流行的Code Project示例項目中下載了可下載的zip。 我們調整了負載測試解決方案以使其與新示例一起使用,然后重新運行測試。 我們確切地經歷了使用別人的代碼(這主要是為什么我們決定接近SO社區)相同的結果。

我們以50 msg / sec的速度發送了20秒鍾,代碼項目示例和我們自己的代碼都平均產生了973/1000次接收操作。 請注意,我們在最基本的水平上進行了測量,以減少錯誤監控的風險。 也就是說,我們在onReceive方法上使用了一個帶有Interlocked.Increment的靜態int- onComplete僅用於異步操作, onComplete!willRaiseEvent均調用onReceive

使用環回地址在一台計算機上執行的所有操作。

在經歷了兩個完全不同的實現的問題之后,我們對負載測試實現表示懷疑。 我們通過Wireshark確認,我們的負載測試項目確實確實按預期發送了流量(pcap日志中存在碎片,但wirehark表示數據包已按預期重組)。 我承認,我對網絡的底層了解比我想要的要弱,但是考慮到碎片數量遠不及丟失消息的數量,我們現在假設兩者不相關。 據我了解,分段應該在較低的層進行處理,並在我們的API調用級別完全抽象化。

@Peter,

公平的說,在正常的聯網情況下,這樣的定時精度絕對是毫無意義的。 但是,等待的實現非常簡單,wireshark確認消息的計時與pcap日志的精度所允許的一樣准確。 鑒於我們僅在回送上進行測試(相同的代碼已部署到Azure雲服務中,一旦達到生產級別,它便是該代碼的預期目標,但是在A0,A1和A8實例上發現的結果相同,即使不是更糟) ),我們想確保一定程度的節流。 如果沒有節流,該代碼將在幾毫秒內輕松推送1000個異步arg,這不是我們要達到的壓力水平。

我同意,因為它是TCP實現,所以我們的代碼中肯定有一個錯誤。 您是否知道鏈接的Code Project示例中的任何錯誤? 因為它表現出與我們的代碼相同的問題。

如預期的那樣,@ usr緩沖區確實包含多個消息。 現在,我們需要弄清楚如何將消息重新結合在一起(TCP保證發送順序,但是在使用多個SAEA時,我們通過線程失去了保證)。

最好的解決方案是放棄自定義TCP協議。 例如,使用HTTP和協議緩沖區。 或者,Web服務。 對於所有這些,都有快速且易於使用的異步庫可用。 假設這不是您想要的:

定義消息框架格式。 例如,在每個消息之前添加BitConvert.GetBytes(messageLengthInBytes) 這樣,您可以解構流。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM