Неизвестная причина истечения времени ожидания для запроса HTTP HEAD - PullRequest
1 голос
/ 09 января 2012

Я использую 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 - нет. Это всегда последние три.

Если я вставлю один из URL-адресов с ошибкой HEAD-запроса в веб-браузер: http://media.server.com/adpm/BED71AD0-2FA5-EA54-0B03-03D139E9242E/videothumb.jpg, изображение будет загружено без проблем.

Чтобы попытаться выяснить, что здесь происходит, я использовал Wireshark для захвата всех HTTP-запросов, отправляемых веб-серверу, на котором размещены изображения. Для примера журнала, который я привел, я вижу 25 запросов HEAD для 25, которые были успешными, но 3, которые потерпели неудачу, НЕ появляются в следе wireshark.

Кроме изображений, имеющих различное визуальное содержание, нет разницы между изображениями.

Чтобы устранить любые проблемы с самим URL (даже если он работает в браузере), я изменил порядок, переключив одно из первых изображений на одно из последних неудачных трех. Когда я делаю это, проблема исчезает для той, которая раньше терпела неудачу, и начинает терпеть неудачу для той, которая была свернута до конца списка.


Так что я думаю, что из вышесказанного я могу сделать вывод, что, когда более 25 запросов HEAD происходят в быстрой последовательности, последующие запросы HEAD не выполняются независимо от конкретного URL. Я также знаю, что проблема связана с сервером IIS, а не с сервером удаленного размещения изображений, из-за отсутствия запросов в трассировке Wireshark после первых 25.

Фрагмент кода, который я использую для выполнения запросов HEAD, показан ниже. Кто-нибудь может дать мне какие-либо предложения относительно того, в чем может быть проблема? Я пробовал различные комбинации значений заголовка запроса, но ни одно из них, похоже, не имеет значения. У меня такое ощущение, что где-то есть некоторые настройки IIS, которые ограничивают число одновременных запросов HttpWebRequests до 25 в любом запросе страницей ASP.NET.

        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 Ответ

1 голос
/ 10 января 2012

Я решил это сам. Проблема действительно заключалась в количестве разрешенных подключений, которое по умолчанию было установлено равным 24.

В моем случае я собираюсь выполнить проверку изображения, только если MyHttpWebRequest.ServicePoint.CurrentConnections меньше 10.

Чтобы увеличить максимальный предел, просто установите для ServicePointManager.DefaultConnectionLimit количество одновременных подключений, которое вам требуется.

Альтернативой, которая может помочь некоторым людям, было бы сокращение времени простоя, то есть времени, в течение которого соединение ожидает, пока оно не разрушится. Чтобы изменить это, вам нужно установить MyHttpWebRequest.ServicePoint.MaxIdleTime на значение времени ожидания в миллисекундах.

...