Dot-Net

WCF - 進行多次呼叫時隨機客戶端超時

  • June 10, 2013

我有一個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 將消息響應的整個數據集載入到記憶體中,然後再將其發送回客戶端。流式傳輸只是將數據發回而不進行緩衝。對於大數據集,它往往快得多,對於小數據集稍慢一些,並且總是使用更少的記憶體(在伺服器和客戶端上)。

引用自:https://stackoverflow.com/questions/16991398