HttpWebRequest的GetResponse或GetRequestStream偶爾超時 + 總結各類超時死掉的可能和相應的解決辦法 【問題】

【問題】html

用C#模擬網頁登錄,其中去請求幾個頁面,會發起對應的http的請求request,其中keepAlive設置爲true,提交請求後,而後會有對應的response:web

resp = (HttpWebResponse)req.GetResponse();c#

以前的屢次調試,一直都是能夠正常得到對應的response,而後讀取html頁面的。服務器

可是後來幾回的調試,在沒有改變代碼的前提下,結果GetResponse卻始終會超時死掉。網絡

 

【解決過程】多線程

1.默認request的timeout是1000000毫秒=100秒,都會超時,手動改成10秒,所以就更容易超時了,沒法解決問題。函數

2.將http的request的keepAlive設置爲false,問題依舊。性能

3.去參考:c# request.GetResponse();超時問題的解決,和HttpWebRequest多線程性能問題,請求超時的錯誤測試

去把前面共4次的httprequest,每次都增長對應的:spa

resp = null; 
。。。 
if (resp != null) 

    resp.Close(); 

if (req != null) 

    req.Abort(); 
}

結果仍是沒解決問題。

4. 一樣參考:HttpWebRequest多線程性能問題,請求超時的錯誤

去嘗試關於DefaultConnectionLimit的設置,改成爲10:

System.Net.ServicePointManager.DefaultConnectionLimit = 10;

問題依舊。

5.又去測試了下,關於response.Close()

也是沒解決問題。

6. 最後無心間,索性不抱但願的,再次DefaultConnectionLimit設置爲更大的值50:

System.Net.ServicePointManager.DefaultConnectionLimit = 50;

試了試,結果就解決超時的問題了。

而後才搞懂緣由。

以前默認設置爲2,後來改成10,都沒有解決問題的緣由在於,當前有不少個http的鏈接,沒有被關閉掉,

而這些keepalive的鏈接,都是

因爲代碼中,對於前面多個request。其都是keepalive爲true,以及多個response也沒有close,

而以前調試了不少次了,因此,此時已經存在了不少個alive的http鏈接了,已經超過了10個了,因此前面設置了DefaultConnectionLimit 爲10,也仍是沒用的。

而改成50,纔夠用。

【總結】

此處GetResponse超過的緣由是,當前存在太多數目的alive的http鏈接(大於10個),因此再次提交一樣的http的request,再去GetResponse,就會超時死掉。

解決辦法就是,把DefaultConnectionLimit 設置爲一個比較大一點的數值,此數值保證大於你當前已經存在的alive的http鏈接數便可。

【經驗總結】

之後寫http的request代碼,若是不是必須的要keepalive的,那麼就要設置KeepAlive爲false:

req.KeepAlive = false;

以及作對應的收尾動做:

if (resp != null) 

    resp.Close(); 

if (req != null) 

    req.Abort(); 
}

 

【後記 2012-03-01】

又偶爾遇到一次,DefaultConnectionLimit已是200了,足夠大了,可是GetResponse和GetRequestStream,仍是會超時死掉的問題,具體是什麼緣由致使的還不是很清楚,可是通過折騰,參考:

HttpWebResponse’s GetResponse() hangs and timeouts

在:

req = (HttpWebRequest)WebRequest.Create(constSkydriveUrl); 
setCommonHttpReqPara(ref req); 
resp = (HttpWebResponse)req.GetResponse();

以前,添加一句垃圾回收:

System.GC.Collect();

而後就解決了GetResponse的超時問題,而且後面的GetRequestStream也同時能夠正常工做,不超時了。

因此,看起來像是當前系統因爲調試屢次,而且HttpWebRequest和HttpWebResponse都是沒有正常去Close的,可能會殘留一些http的連接,而後就可能影響到了後續對於http的使用,垃圾回收後,估計就把殘餘的http相關資源釋放了,而後http就能夠正常工做了。

 

【總結】

對於GetResponse或GetRequestStream超時死掉的緣由,多是:

1.DefaultConnectionLimit是默認的2,而當前的Http的connection用完了,致使後續的GetResponse或GetRequestStream超時死掉

==>> 默認系統只支持同時存在2個http的connection

==>> 使用HttpWebRequest以後若是沒有close,則會佔用1個http的connection,因此若是超過2次使用HttpWebRequest而沒有close,那麼就用完系統的http的connection,以後再去使用HttpWebRequest,GetResponse就會死掉

解決辦法:

辦法1:

每次使用完HttpWebRequest,使用

1
2
req.Close();
req= null ;

去關閉對應的http connection

最好對應的HttpWebResponse也要close:

1
2
resp.Close();
resp =  null ;

方法2:

修改DefaultConnectionLimit的值,改成足夠大,好比:

1
System.Net.ServicePointManager.DefaultConnectionLimit = 200;

 

2.系統中Http相關的資源沒有正確釋放,致使後續GetResponse或GetRequestStream超時死掉

就像我此處遇到的,多是以前調用http相關函數,沒有正確徹底釋放資源,致使雖然DefaultConnectionLimit給了足夠大,可是仍是會死掉,此時在http請求代碼以前去作一次垃圾回收,則後續http的GetResponse或GetRequestStream就正常了,就不會超時死掉了。

參考代碼以下:

1
2
3
4
5
System.GC.Collect();
 
req = (HttpWebRequest)WebRequest.Create(constSkydriveUrl);
setCommonHttpReqPara( ref  req);
resp = (HttpWebResponse)req.GetResponse();

 

3.Http的GET請求時,不要手動設置ContentLength的值

這個是參考這裏:HttpWebRequest.GetResponse() hangs the second time it is called而記錄於此的,也許有人是此緣由,因此可供參考一下。

即Http的GET請求,不要添加相似以下的代碼:

1
2
if  (m_contentLength > 0)
     httpWebRequest.ContentLength = m_contentLength;

不要去手動修改對應的ContentLength的值,C#的http相關庫函數,會自動幫你計算的。

注:POST方法中,的確是要手動填充數據和算出數據大小,而後手動給ContentLength賦值的。

 

4.其餘可能的一些緣由

(1)關於KeepAlive的問題

若是Http的請求,是設置了KeepAlive=true的話,那麼對應的http的connection會和服務器保持鏈接的。

因此若是上述辦法都不能解決超時的問題,能夠嘗試將keepAlive設置爲false試試,看看可否解決。

(2)關於Sleep

有些人好像是經過在http請求前,加了對應的Sleep,結果解決了此問題。須要的人,也能夠試試。

(3)HttpWebRequest的Timeout

通常來講,既然超時了,每每是因爲錯誤使用函數或者網絡有問題致使的,因此實際上此處對於有些人去把HttpWebRequest的Timeout的值改的更大,每每都是沒用的。

只不過,萬一是因爲網絡響應慢而致使超時,那麼卻是能夠嘗試,將HttpWebRequest的Timeout的值改成更大。

(其中HttpWebRequest的Timeout默認的值是100,000 milliseconds ==100 seconds)

參考代碼:

req.Timeout = 5 * 60 * 1000; // 5 minutes

原文連接:https://www.cnblogs.com/summer_adai/archive/2013/04/26/3045253.html

相關文章
相關標籤/搜索