[英]Adjusting HttpWebRequest Connection Timeout in C#
我相信經過漫長的研究和搜索,我發現我想做的事情可能更好,通過建立一個異步連接並在所需的超時后終止它...但是我會繼續問無論如何!
快速代碼片段:
HttpWebRequest webReq = (HttpWebRequest)HttpWebRequest.Create(url);
webReq.Timeout = 5000;
HttpWebResponse response = (HttpWebResponse)webReq.GetResponse();
// this takes ~20+ sec on servers that aren't on the proper port, etc.
我有一個HttpWebRequest
方法,它位於多線程應用程序中,我連接到大量的公司Web服務器。 如果服務器沒有響應, HttpWebRequest.GetResponse()
大約需要20秒才能超時,即使我指定的超時時間僅為5秒。 為了定期通過服務器,我想跳過連接時間超過5秒的服務器。
所以問題是: “是否有一種簡單的方法來指定/減少WebRequest或HttpWebRequest的連接超時?”
我認為問題在於WebRequest
僅在實際發出請求后才測量時間。 如果您向同一地址提交多個請求,那么ServicePointManager
將限制您的請求,並且實際上只提交與相應ServicePoint.ConnectionLimit
的值一樣多的並發連接,默認情況下,它從ServicePointManager.DefaultConnectionLimit
獲取值。 應用程序CLR主機將此設置為2,ASP主機設置為10.因此,如果您有一個多線程應用程序向同一主機提交多個請求,則實際上只有兩個請求放在線路上,其余的排隊等待。
我還沒有研究過這個確鑿的證據,證明這是真的發生了什么,但是在一個類似的項目中,我發現事情是可怕的,直到我刪除了ServicePoint
限制。
另一個要考慮的因素是DNS查找時間。 同樣,我相信沒有確鑿的證據支持,但我認為WebRequest
不計入請求超時的DNS查找時間。 DNS查找時間可能會在某些部署中顯示為非常大的時間因素。
是的,您必須圍繞WebRequest.BeginGetRequestStream
(對於帶內容的POST
)和WebRequest.BeginGetResponse
(對於GET
和 POSTS
)編寫應用程序。 同步調用不會擴展(我不會詳細說明為什么,但我確實有確鑿的證據)。 無論如何, ServicePoint
問題與此正交:排隊行為也發生在異步調用上。
很抱歉找到一個舊線程,但我認為上面提到的內容可能不正確/誤導。
從我所知道的.Timeout不是連接時間,它是HttpWebRequest和響應的整個生命周期所允許的總時間。 證明:
我設置:
.Timeout=5000
.ReadWriteTimeout=32000
HttpWebRequest的連接和發布時間為26ms
但隨后的調用HttpWebRequest.GetResponse()在4974ms超時,從而證明5000ms是整個發送請求/獲取響應調用集的時間限制。
我沒有驗證DNS名稱解析是否作為時間的一部分被測量,因為這與我無關,因為這一切都不是我真正需要它工作的方式 - 我的意圖是在連接到系統時更快地超時如果在請求的連接階段失敗,則不接受連接。
例如:我願意在有可能返回結果的連接請求上等待30秒,但我只想等待10秒鍾等待向一個行為不端的主機發送請求。
我后來發現有幫助的東西是.ReadWriteTimeout
屬性。 除了.Timeout
屬性之外,這似乎最終減少了線程花在嘗試從有問題的服務器上下載的時間。 .ReadWriteTimeout
的默認時間是5分鍾,對於我的應用程序來說太長了。
所以,在我看來:
.Timeout
=嘗試建立連接所花費的時間(不包括查找時間) .ReadWriteTimeout
=建立連接后嘗試讀取或寫入數據所花費的時間
更多信息: HttpWebRequest.ReadWriteTimeout屬性
編輯:
根據Per @ KyleM的評論, Timeout
屬性用於整個連接嘗試,並在MSDN上閱讀它顯示:
Timeout是使用GetResponse方法進行的后續同步請求等待響應的毫秒數,GetRequestStream方法等待流。 Timeout適用於整個請求和響應,而不是單獨應用於GetRequestStream和GetResponse方法調用。 如果在超時期限內未返回資源,則該請求將拋出WebException,並將Status屬性設置為WebExceptionStatus.Timeout。
(強調我的。)
從HttpWebRequest.Timeout屬性的文檔:
域名系統(DNS)查詢最多可能需要15秒才能返回或超時。 如果您的請求包含需要解析的主機名,並且您將Timeout設置為小於15秒的值,則可能需要15秒或更長時間才能引發WebException以指示請求超時。
您的DNS查詢是否可能是超時的原因?
無論我們嘗試什么,當我們檢查的服務器關閉時,我們無法設置超過21秒的超時。
為了解決這個問題,我們結合了一個TcpClient檢查來查看域是否還活着,然后單獨檢查以確定URL是否處於活動狀態
public static bool IsUrlAlive(string aUrl, int aTimeoutSeconds)
{
try
{
//check the domain first
if (IsDomainAlive(new Uri(aUrl).Host, aTimeoutSeconds))
{
//only now check the url itself
var request = System.Net.WebRequest.Create(aUrl);
request.Method = "HEAD";
request.Timeout = aTimeoutSeconds * 1000;
var response = (HttpWebResponse)request.GetResponse();
return response.StatusCode == HttpStatusCode.OK;
}
}
catch
{
}
return false;
}
private static bool IsDomainAlive(string aDomain, int aTimeoutSeconds)
{
try
{
using (TcpClient client = new TcpClient())
{
var result = client.BeginConnect(aDomain, 80, null, null);
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(aTimeoutSeconds));
if (!success)
{
return false;
}
// we have connected
client.EndConnect(result);
return true;
}
}
catch
{
}
return false;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.