關於wcf 的連線逾時問題,wcf連線逾時
今天網上的系統突然報錯,經過排查是調用wcf報錯了,報錯資訊如下:
System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:00. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The request operation did not complete within the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout.
at System.ServiceModel.Channels.ReliableRequestSessionChannel.SyncRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
--- End of inner exception stack trace ---
網上找了半天資料,這篇文章是很有價值的
I also had this timeout problem. The client requests to my WCF service would work 3 to 6 times, then it would fail with a timeout. I was passing tiny messages back and forth, so I knew "I cannot accomplish such big error with such tiny messages" ;-)
The problem was I was forgetting to call .Close() on the WCF client object! Once I added the appropriate ".Close()", the error disappeared.
So once you're done calling the WCF service, make sure to call Close(), probably in your Finally block.
經過排查確實是相關的部門調了這個服務,沒有加.Close().導致的.
在這個部門沒有修改代碼之前,伺服器的配置如果需要修改,可以增加service的配置串連數
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="10000000"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="100" maxConcurrentInstances="100" />
</behavior>
</serviceBehaviors>
如果wcf是宿主在iis上的,可以增加iis的全域配置
http://www.cnblogs.com/z2002m/archive/2012/10/26/1918342.html
這篇很有價值了
IIS的MaxConnection的驗證
最近公司有位仁兄寫了一個監控IIS的軟體,裡面提到一個串連數, 此串連數主要是收集WMI資訊,
把代碼寫一下:
// 取到IIS的各個網站
System.Management.ManagementClass mc = new System.Management.ManagementClass("Win32_PerfFormattedData_W3SVC_WebService");
// 每個網站
foreach (System.Management.ManagementObject obj in mc.GetInstances())
{
// 這裡就是每個網站當前的串連數
Convert.ToInt64(obj.Properties["CurrentConnections"].Value); //
}
乍一看, 此 CurrentConnections是做什麼用的呢? 由於我一直想瞭解一個IIS網站預設在同一時刻究竟能接受多少串連請求, 上網查了查,查到了maxconnection。
首先看看微軟是怎麼解釋的:
The maxconnection parameter determines how many connections can be made to a specific IP address.
這個 maxconnection參數用來確定: 對於每個IP能容納多少個串連數(翻譯的並不一定準)。
<connectionManagement>
<add address="*" maxconnection="2"> // 這裡就說明是2個
</connectionManagement>
這個 maxconnection會不會是並發串連數呢?
我們來看看 http://www.microsofttranslator.com/BV.aspx?ref=CSSKB&from=en&to=zh-chs&a=http://support.microsoft.com/kb/821268/en-us?fr=1
裡面有一段寫的很明白,
- maxWorkerThreads 參數和 maxIoThreads 參數的值設定為 100。
- maxconnection 參數的值設定 12 * N (其中,N 是您的 cpu 的數量)。
- 設定要 minFreeThreads 參數的值 88 * N 和 minLocalRequestFreeThreads 參數,76 * N。
- minWorkerThreads 的值設定為 50。請記住 minWorkerThreads 不是預設的設定檔中。您必須添加它。
這些建議的一些涉及一個簡單的公式,涉及在伺服器上的 cpu 數量。N 表示公式中的 cpu 數量的變數。這些的設定如果您有超執行緒啟用,您必須使用邏輯 cpu 數而不是物理 cpu 數。例如如果啟用超執行緒與四個處理器的伺服器然後 N 公式中的值將是
8,而不是
4。
請注意在使用此配置時您可以執行的每個 CPU 12 ASP.NET 請求最多在同一時間因為 100-88 = 12。因此,至少 88 * N 背景工作執行緒和 88 * N 完成連接埠線程都可用的其它用途 (例如 Web 服務回調)。
基本上就明白了。 maxconnection = 12*CPU數量。 我們公司的伺服器是使用雙核的, 也就是說,在預設的情況下,
我們公司伺服器上的IIS網站的預設最大串連數是24,
接下來驗證一下, 測試的目的是為了證明: 當超過24個訪問串連候,IIS的網站還能不能接受其他的串連,
實現準備:
1 寫一個WEBService,裡麵包括A和B方法,其中A方法裡面就一句Thread.Sleep(十分鐘), 而B方法則直接Return "OK";
2 VS2008負載測試(類比24個使用者同時訪問一台伺服器上的webServiceA方法,因為A方法是會讓線程休眠十分鐘)
3 同時在伺服器上收集WMI資訊來觀測WEBService當前的串連數, 使用: obj.Properties["CurrentConnections"].Value (具體收集方法看本文開頭)
這是負載測試,
這是負載測試調用的測試方法。
OK, 準備就緒, 開吃。。哦,不對, 開始測試,這裡我就不貼出來當時測試的圖, 我把我測試的結果告之一下,
當負載測試開始, Webservicer 的 obj.Properties["CurrentConnections"].Value 值,一直在增加, 當增加到24時,也就是我們類比的24個使用者,
我們在本機再類比編寫一段訪問WebServiceB方法的代碼,注意B方法是不會使線程休眠的,直接Return "ok" . 結果一直等到逾時,也沒有OK顯示,
但此時 obj.Properties["CurrentConnections"].Value的值為25,
如果我們把負載並發數的設為23呢,再啟動負載測試, 當串連數達到23時, 再調用B方法,結果發現,大約在三秒鐘,調用B方法成功了,顯示“OK”,
順便提一句:在ASP.NET 2.0中,引入了autoConfig屬性:
1 |
< processModel autoConfig = "true" /> |
當值為true時,autoConfig在運行時修改配置如下:
- 設定maxWorkerThreaders和maxIoThreads為100
- 設定maxconnection 為12*CPU數量
- 設定minFreeThreads為88*CPU數量
- 設定minWorkerThreads為50
如果大家說, 我有一台猛機, 配置牛B, 這些預設的設定不夠,我需要自已動用配置, OK, 可以直接在machine.config裡修改,
下面是範例程式碼,
<system.net>
<connectionManagement>
<add address = "*" maxconnection = "24" />
</connectionManagement>
</system.net>
<system.web>
<httpRuntime minFreeThreads="176" minLocalRequestFreeThreads="152"/>
<processModel autoConfig="false" maxWorkerThreads="100" maxIoThreads="100"/>
有些人會問: 這個東東一定要在 machine.config裡修改嗎? 能不能在web.config裡面呢,目前我在Webserive程式裡面的Web.config
修改了 <add address = "*" maxconnection = "30" />, 但使用負載測試時,發現還是不行,只能達到24, 這就說明30並未起作用。
有知道的說明一下,為什麼不行? 按照微軟的說明,應該在web.config裡面是可以起作用的,
需要注意的是: 如果增加了maxconnection 數量, maxWorkerThreads的數量也需要增加相當的數量, 比如在雙核的CPU上, 修改maxconnection = 25,
則 maxWorkerThreads也需要修改為101, 因為 maxconnection = maxWorkerThreads --minFreeThreads
還有一個疑問: 如果IIS崩潰了, 這裡正好有一個HTTP請求過來,那麼IIS會怎麼處理? 答案中最好有微軟的官方說明。
結論: IIS的網站預設的並發串連數是12*CPU,也就是說預設設定下IIS在同一時刻能處理的最大請求數是12*CPU數量 。
歡迎猛烈拍磚,有什麼好建議你老就使勁的提吧。謝謝你了。