C#中HttpWebRequest的GetRequestStream執行的效率太低,甚至偶爾死掉
C#中HttpWebRequest的GetRequestStream執行的效率太低,甚至偶爾死掉
2014-04-19 15:14 3290人閱讀 評論(0) 收藏 舉報 分類:
為了提高httpwebrequest的執行效率,查到了一些如下設定
request.ServicePoint.Expect100Continue = false;
request.ServicePoint.UseNagleAlgorithm = false;
request.ServicePoint.ConnectionLimit = 65500;
request.AllowWriteStreamBuffering = false; request.Proxy = null;
然後就看到了如下相關的一些文章,記錄下來:
轉:C#中HttpWebRequest的GetRequestStream執行的效率太低,甚至偶爾死掉
用C#模擬網頁登陸,其中去請求幾個頁面,會發起對應的http的請求request,其中keepAlive設定為true,提交請求後,然後會有對應的response:
resp = (HttpWebResponse)req.GetResponse();
之前的多次除錯,一直都是可以正常獲得對應的response,然後讀取html頁面的。
但是後來幾次的除錯,在沒有改變程式碼的前提下,結果GetResponse卻始終會超時死掉。
【解決過程】
1.預設request的timeout是1000000毫秒=100秒,都會超時,手動改為10秒,因此就更容易超時了,無法解決問題。
2.將http的request的keepAlive設定為false,問題依舊。
3.去參考:c# request.GetResponse();超時問題的解決,和HttpWebRequest多執行緒效能問題,請求超時的錯誤,
去把前面共4次的httprequest,每次都增加對應的:
resp = null; |
結果還是沒解決問題。
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) |
【後記 2012-03-01】
又偶爾遇到一次,DefaultConnectionLimit已經是200了,足夠大了,但是GetResponse和GetRequestStream,還是會超時死掉的問題,具體是什麼原因導致的還不是很清楚,但是經過折騰,參考:
HttpWebResponse’s GetResponse() hangs and timeouts
在:
req = (HttpWebRequest)WebRequest.Create(constSkydriveUrl); |
之前,新增一句垃圾回收:
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)
為了提高httpwebrequest的執行效率,查到了一些如下設定
request.ServicePoint.Expect100Continue = false;
request.ServicePoint.UseNagleAlgorithm = false;
request.ServicePoint.ConnectionLimit = 65500;
request.AllowWriteStreamBuffering = false; request.Proxy = null;
然後就看到了如下相關的一些文章,記錄下來:
轉:C#中HttpWebRequest的GetRequestStream執行的效率太低,甚至偶爾死掉
用C#模擬網頁登陸,其中去請求幾個頁面,會發起對應的http的請求request,其中keepAlive設定為true,提交請求後,然後會有對應的response:
resp = (HttpWebResponse)req.GetResponse();
之前的多次除錯,一直都是可以正常獲得對應的response,然後讀取html頁面的。
但是後來幾次的除錯,在沒有改變程式碼的前提下,結果GetResponse卻始終會超時死掉。
【解決過程】
1.預設request的timeout是1000000毫秒=100秒,都會超時,手動改為10秒,因此就更容易超時了,無法解決問題。
2.將http的request的keepAlive設定為false,問題依舊。
3.去參考:c# request.GetResponse();超時問題的解決,和HttpWebRequest多執行緒效能問題,請求超時的錯誤,
去把前面共4次的httprequest,每次都增加對應的:
resp = null; |
結果還是沒解決問題。
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) |
【後記 2012-03-01】
又偶爾遇到一次,DefaultConnectionLimit已經是200了,足夠大了,但是GetResponse和GetRequestStream,還是會超時死掉的問題,具體是什麼原因導致的還不是很清楚,但是經過折騰,參考:
HttpWebResponse’s GetResponse() hangs and timeouts
在:
req = (HttpWebRequest)WebRequest.Create(constSkydriveUrl); |
之前,新增一句垃圾回收:
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 |