HTTP HEAD请求超时的未知原因

时间:2012-01-09 15:41:55

标签: asp.net http iis httpwebrequest head

我正在使用ASP.NET 3.5构建一个网站。该网站的一个区域显示了28个视频缩略图,这是jpeg托管在另一个网络服务器上。如果这些jpeg中不存在一个或多个,我想向用户显示本地托管的默认图像,而不是浏览器中的图像链接。

我实现这一点的方法是每当呈现页面时,它将对每个图像执行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请求网址粘贴到网络浏览器中:http://media.server.com/adpm/BED71AD0-2FA5-EA54-0B03-03D139E9242E/videothumb.jpg,它会毫无问题地加载图片。

为了解决这里发生的事情,我使用Wireshark捕获发送到托管图像的Web服务器的所有HTTP请求。对于我给出的日志示例,我可以看到25个成功的HEAD请求,但失败的3个请求不会出现在wireshark跟踪中。

除了具有不同视觉内容的图像之外,从一个图像到下一个图像没有区别。

要消除URL本身的任何问题(即使它在浏览器中有效),我通过使用最后一个失败的三个图像之一切换其中一个图像来更改顺序。当我这样做时,问题就会消失,对于那个过去失败的问题,并且开始失败的那个被击倒到列表的末尾。


所以我认为我可以从上面推断,当快速连续发生超过25个HEAD请求时,无论特定URL如何,后续HEAD请求都会失败。我也知道问题出在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;
        }

1 个答案:

答案 0 :(得分:1)

我自己解决了这个问题。问题确实是允许的连接数,默认设置为24。

就我而言,如果MyHttpWebRequest.ServicePoint.CurrentConnections小于10,我将只执行图像检查。

要增加最大限制,只需将ServicePointManager.DefaultConnectionLimit设置为您需要的并发连接数。

一种可以帮助某些人减少空闲时间的替代方案,即连接等待直至其自身破坏的时间。要更改此设置,您需要将MyHttpWebRequest.ServicePoint.MaxIdleTime设置为超时值(以毫秒为单位)。