我使用ASP.NET 3.5構建網站。該網站的一個區域顯示了28個視頻縮略圖圖像,這些圖像是在另一個網絡服務器上託管的jpeg。如果這些jpeg中的一個或多個不存在,我想向用戶顯示本地託管的默認圖像,而不是瀏覽器中的圖像鏈接斷開。HTTP HEAD請求超時的未知原因
我採取的方法是每當呈現頁面時,它都會對每個圖像執行HTTP HEAD請求。如果我得到一個200 OK狀態碼,那麼圖像很好,我可以寫出<img src="http://media.server.com/media/123456789.jpg" />
。如果我得到404 Not Found,那麼我寫出<img src="/images/defaultthumb.jpg" />
。
如果當然我不希望每次都爲所有請求執行此操作,因此我已經實現了存儲在應用程序級別的緩存圖像狀態對象列表,以便每個圖像每隔5分鐘只檢查一次用戶,但這對我的問題沒有任何影響。
這似乎工作得很好。我的問題是,對於特定的圖像,HTTP HEAD請求失敗,請求超時。
我已將超時值設置爲非常低,只有200毫秒,因此不會延遲頁面渲染太多。對於大多數圖像來說,這種超時似乎是正確的,我試着在調試過程中四處遊玩並增加它,但即使超過10秒也沒什麼區別。
我寫了一個日誌文件,看看發生了什麼,這就是我得到(編輯爲澄清和匿名):
14:24:56.799|DEBUG|[HTTP HEAD CHECK OK [http://media.server.com/adpm/505C3080-EB4F-6CAE-60F8-B97F77A43A47/videothumb.jpg]]
14:24:57.356|DEBUG|[HTTP HEAD CHECK OK [http://media.server.com/adpm/66E2C916-EEB1-21D9-E7CB-08307CEF0C10/videothumb.jpg]]
14:24:57.914|DEBUG|[HTTP HEAD CHECK OK [http://media.server.com/adpm/905C3D99-C530-46D1-6B2B-63812680A884/videothumb.jpg]]
...
14:24:58.470|DEBUG|[HTTP HEAD CHECK OK [http://media.server.com/adpm/1CE0B04D-114A-911F-3833-D9E66FDF671F/videothumb.jpg]]
14:24:59.027|DEBUG|[HTTP HEAD CHECK OK [http://media.server.com/adpm/C3D7B5D7-85F2-BF12-E32E-368C1CB45F93/videothumb.jpg]]
14:25:11.852|ERROR|[HTTP HEAD CHECK ERROR [http://media.server.com/adpm/BED71AD0-2FA5-EA54-0B03-03D139E9242E/videothumb.jpg]] The operation has timed out
Source: System
Target Site: System.Net.WebResponse GetResponse()
Stack Trace: at System.Net.HttpWebRequest.GetResponse()
at MyProject.ApplicationCacheManager.ImageExists(String ImageURL, Boolean UseCache) in d:\Development\MyProject\trunk\src\Web\App_Code\Common\ApplicationCacheManager.cs:line 62
14:25:12.565|ERROR|[HTTP HEAD CHECK ERROR [http://media.server.com/adpm/92399E61-81A6-E7B3-4562-21793D193528/videothumb.jpg]] The operation has timed out
Source: System
Target Site: System.Net.WebResponse GetResponse()
Stack Trace: at System.Net.HttpWebRequest.GetResponse()
at MyProject.ApplicationCacheManager.ImageExists(String ImageURL, Boolean UseCache) in d:\Development\MyProject\trunk\src\Web\App_Code\Common\ApplicationCacheManager.cs:line 62
14:25:13.282|ERROR|[HTTP HEAD CHECK ERROR [http://media.server.com/adpm/7728C3B6-69C8-EFAA-FC9F-DAE70E1439F9/videothumb.jpg]] The operation has timed out
Source: System
Target Site: System.Net.WebResponse GetResponse()
Stack Trace: at System.Net.HttpWebRequest.GetResponse()
at MyProject.ApplicationCacheManager.ImageExists(String ImageURL, Boolean UseCache) in d:\Development\MyProject\trunk\src\Web\App_Code\Common\ApplicationCacheManager.cs:line 62
正如你可以看到,第一個25 HEAD請求的工作,和最後3不要。它總是最後三個。
如果我將其中一個失敗的HEAD請求URL粘貼到網絡瀏覽器中:http://media.server.com/adpm/BED71AD0-2FA5-EA54-0B03-03D139E9242E/videothumb.jpg
,它會加載沒有問題的圖像。
爲了弄清楚這裏發生了什麼,我使用Wireshark捕獲發送到託管圖像的Web服務器的所有HTTP請求。對於我給出的日誌示例,我可以看到25個HEAD請求成功,但失敗的3個請求不會出現在wireshark跟蹤中。
除了具有不同視覺內容的圖像之外,從一個圖像到下一個圖像沒有區別。
爲了消除與自身的URL(即使它工作在一個瀏覽器)我通過切換第一圖像中的一個與最後一個失敗了的順序改變了什麼問題。當我這樣做時,問題就會消失,因爲過去常常失敗的問題就會消失,並且會出現失敗,因爲碰到了列表末尾的問題。
所以我想我可以從上面推斷,當超過25個HEAD請求發生在快速連續,隨後HEAD請求失敗不管具體的URL。我也知道這個問題出現在IIS服務器上,而不是遠程圖像託管服務器上,這是由於Wireshark跟蹤超出了前25個請求中的請求。
我用來執行HEAD請求的代碼片段如下所示。任何人都可以給我任何關於什麼可能是問題的建議?我已經嘗試過請求頭值的各種不同組合,但它們都沒有任何區別。我的直覺是有一些IIS設置在任何一個ASP.NET頁面請求中將併發HttpWebRequests的數量限制爲25。
try {
HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(ImageURL);
hwr.Method = "HEAD";
hwr.KeepAlive = false;
hwr.AllowAutoRedirect = false;
hwr.Accept = "image/jpeg";
hwr.Timeout = 200;
hwr.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.Reload);
//hwr.Connection = "close";
HttpWebResponse hwr_result = (HttpWebResponse)hwr.GetResponse();
if (hwr_result.StatusCode == HttpStatusCode.OK) {
Diagnostics.Diags.Debug("HTTP HEAD CHECK OK [" + ImageURL + "]", HttpContext.Current.Request);
// EXISTENCE CONFIRMED - ADD TO CACHE
if (UseCache) {
_ImageExists.Value.RemoveAll(ie => ie.ImageURL == ImageURL);
_ImageExists.Value.Add(new ImageExistenceCheck() { ImageURL = ImageURL, Found = true, CacheExpiry = DateTime.Now.AddMinutes(5) });
}
// RETURN TRUE
return true;
} else if (hwr_result.StatusCode == HttpStatusCode.NotFound) {
throw new WebException("404");
} else {
throw new WebException("ERROR");
}
} catch (WebException ex) {
if (ex.Message.Contains("404")) {
Diagnostics.Diags.Debug("HTTP HEAD CHECK NOT FOUND [" + ImageURL + "]", HttpContext.Current.Request);
// NON-EXISTENCE CONFIRMED - ADD TO CACHE
if (UseCache) {
_ImageExists.Value.RemoveAll(ie => ie.ImageURL == ImageURL);
_ImageExists.Value.Add(new ImageExistenceCheck() { ImageURL = ImageURL, Found = false, CacheExpiry = DateTime.Now.AddMinutes(5) });
}
return false;
} else {
Diagnostics.Diags.Error(HttpContext.Current.Request, "HTTP HEAD CHECK ERROR [" + ImageURL + "]", ex);
// ASSUME IMAGE IS OK
return true;
}
} catch (Exception ex) {
Diagnostics.Diags.Error(HttpContext.Current.Request, "GENERAL CHECK ERROR [" + ImageURL + "]", ex);
// ASSUME IMAGE IS OK
return true;
}