WCF - 進行多次呼叫時隨機客戶端超時
我有一個
WPF客戶通過WCF託管在IIS 7. 服務方法呼叫儲存過程 (SQL 2012)EF用於檢索一些數據。需要載入大量數據,因此客戶端會多次呼叫服務方法,以“分解”數據載入並避免大量有效負載和超時。
我們使用生成的服務代理從
System.ServiceModel.ClientBase<T>.我們還使用了帶有二進制編碼的自定義 http 綁定(來自此處) - 此處顯示的實際實現:
<customBinding> <binding name="CustomBinding_IPointDataAccess" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"> <binaryMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" maxSessionSize="2048"> <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="16384" /> </binaryMessageEncoding> <httpTransport manualAddressing="false" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true" maxBufferSize="2147483647" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true" /> </binding>此外,在 IIS 中打開了動態壓縮。我可以在 Fiddler 中查看請求,消息正文的大小很好(~50KB),99% 的請求在一兩秒內返回。完美的!
但是,幾乎在每次迭代中,都有一個呼叫需要幾分鐘才能完成,我不知道為什麼……我
sendTimeOut在客戶端上的時間是 1 分鐘,自然一個呼叫會失敗。我將它延長到 10 分鐘,通話似乎在 2 分鐘多一點內完成——儘管有時需要更長的時間。問題看起來非常隨機 - 它可能是第一次呼叫,也可能是第 30 次呼叫。但它的重現性非常好。我在 WCF 服務方法中的儲存過程呼叫周圍放置了一些日誌記錄,它會在一秒鐘內執行並獲取數據。所以,我認為這不是數據庫問題。
使用 Fiddler,有問題的呼叫會生成類似於以下內容的輸出:
ACTUAL PERFORMANCE -------------- ClientConnected: 14:02:42.959 ClientBeginRequest: 14:03:01.224 GotRequestHeaders: 14:03:01.224 ClientDoneRequest: 14:03:01.574 Determine Gateway: 0ms DNS Lookup: 0ms TCP/IP Connect: 46ms HTTPS Handshake: 0ms ServerConnected: 14:05:16.021 FiddlerBeginRequest: 14:05:16.021 ServerGotRequest: 14:05:16.021 ServerBeginResponse: 14:03:04.784 GotResponseHeaders: 14:05:16.561 ServerDoneResponse: 14:05:16.611 ClientBeginResponse: 14:05:16.611 ClientDoneResponse: 14:05:16.611
ServerBeginResponse注意和之間的重要時間GotResponseHeaders。這似乎與這裡看到的問題驚人地相似。我啟用了 WCF 服務跟踪,並且快速瀏覽了一下,沒有錯誤或警告,但我無法真正理解超出基礎的內容。
我怎樣才能確定問題出在什麼地方?是序列化嗎?是網路問題嗎?伺服器能跟不上客戶端發送這麼多請求的速度嗎?
我已經嘗試通過添加適當的 來調整配置文件中的 WCF Throttling
serviceBehaviors,但這並沒有什麼不同。我應該提一下,我是通過 VPN 連接執行此操作的,但文件傳輸、遠端桌面連接等其他事情也可以正常工作。看起來還挺靠譜的。
如有必要,我可以提供更多詳細資訊。
**編輯(6.10.2013):**不確定這是相關還是只是僥倖,但有幾次,我注意到在有問題的呼叫中,身體尺寸明顯小於其他尺寸。並非每次都是如此,但它可能會提供一些線索。這是 Fiddler 的螢幕截圖,向您展示了 Body 大小與每次呼叫的一致性。所選條目 (#21) 的大小比其他條目小得多,但需要 2 多分鐘才能完成。
奇怪的是,這一次我收到了一個例外。異常並非每次都發生。
System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error. Server stack trace: at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
正如我在評論中建議的那樣,請嘗試將傳輸模式設置為流式傳輸,以排除這是與記憶體壓力相關的問題的可能性(因為流式傳輸模式應該導致 wcf 使用更少的記憶體)。
當我看到這個問題時懷疑這可能是問題,因為它似乎只發生在您快速連續進行許多服務呼叫時。根據我的經驗,這通常是兩個問題之一:代理沒有從客戶端正確關閉,或者由於記憶體壓力,伺服器正在執行 GC。
當傳輸模式被緩衝時,WCF 將消息響應的整個數據集載入到記憶體中,然後再將其發送回客戶端。流式傳輸只是將數據發回而不進行緩衝。對於大數據集,它往往快得多,對於小數據集稍慢一些,並且總是使用更少的記憶體(在伺服器和客戶端上)。
