簡體   English   中英

在C#中調整HttpWebRequest連接超時

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM