HttpWebRequest очень медленно! - PullRequest
68 голосов
/ 26 марта 2010

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

Ruby-программа: 2.11 секунды для 10 HTTP GETs

Ruby-программа: 18,13 секунды для 100 HTTP GETs

C # библиотека: 20,81 секунды для 10 HTTP GETs

Библиотека C #: 36847,46 секунд для 100 HTTP GETs

Я профилировал и обнаружил, что проблема заключается в этой функции:

private HttpWebResponse GetRawResponse(HttpWebRequest request) {
  HttpWebResponse raw = null;
  try {
    raw = (HttpWebResponse)request.GetResponse(); //This line!
  }
  catch (WebException ex) {
    if (ex.Response is HttpWebResponse) {
      raw = ex.Response as HttpWebResponse;
    }
  }
  return raw;
}

Отмеченная строка занимает более 1 секунды, чтобы завершиться сама по себе, в то время как программа ruby, выполняющая 1 запрос, занимает 0,3 секунды. Я также делаю все эти тесты на 127.0.0.1, поэтому пропускная способность сети не является проблемой.

Что может быть причиной такого огромного замедления?

UPDATE

Проверьте измененные результаты тестов. Я на самом деле тестировал с 10 GET, а не 100, я обновил результаты.

Ответы [ 11 ]

169 голосов
/ 30 августа 2010

Основным виновником медленных веб-запросов я считаю свойство прокси. Если перед вызовом метода GetResponse установить для этого свойства значение null, запрос пропустит шаг автоопределения прокси:

request.Proxy = null;
using (var response = (HttpWebResponse)request.GetResponse())
{
}

Автообнаружение прокси занимало до 7 секунд, прежде чем возвращать ответ. Немного раздражает, что это свойство установлено по умолчанию для объекта HttpWebRequest.

20 голосов
/ 26 марта 2010

Возможно, это связано с тем, что вы открываете несколько соединений одновременно. По умолчанию Максимальное количество открытых HTTP-соединений установлено на два. Попробуйте добавить это в ваш файл .config и посмотрите, поможет ли это:

<system.net>
  .......
  <connectionManagement>
    <add address="*" maxconnection="20"/>
  </connectionManagement>
</system.net>
10 голосов
/ 15 января 2013

У меня была похожая проблема с проектом VB.Net MVC.
Локально на моем компьютере (Windows 7) на запрос страницы уходило менее 1 секунды, а на сервере (Windows Server 2008 R2) - 20+ секунд на каждый запрос страницы.

Я попробовал комбинацию установки прокси на ноль

  System.Net.WebRequest.DefaultWebProxy = Nothing
  request.Proxy = System.Net.WebRequest.DefaultWebProxy

И изменить файл конфигурации, добавив

 <system.net>
   .......
   <connectionManagement>
     <add address="*" maxconnection="20"/>
   </connectionManagement>
 </system.net>

Это по-прежнему не уменьшало время медленного запроса страницы на сервере. В конце концов решением было снять флажок «Автоматически определять настройки» в параметрах IE на самом сервере. (В разделе «Сервис» -> «Свойства обозревателя» выберите вкладку «Подключения». Нажмите кнопку «Настройки ЛВС»)

Сразу после того, как я отключил эту опцию браузера на сервере, все время запроса страницы сократилось с 20+ секунд до менее 1 секунды.

8 голосов
/ 31 января 2014

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

ServicePointManager.DefaultConnectionLimit = 4;

Но после создания этого количества веб-запросов задержки вернулись.

Проблема, в моем случае, заключалась в том, что я звонил POST и не беспокоился об ответе, поэтому не принимал и ничего не делал с ним. К сожалению, это привело к тому, что WebRequest не работал до истечения времени ожидания.

Исправление было в том, чтобы взять Ответ и просто закрыть его.

WebRequest webRequest = WebRequest.Create(sURL);
webRequest.Method = "POST";
webRequest.ContentLength = byteDataGZ.Length;
webRequest.Proxy = null;
using (var requestStream = webRequest.GetRequestStream())
{
    requestStream.WriteTimeout = 500;
    requestStream.Write(byteDataGZ, 0, byteDataGZ.Length);
    requestStream.Close();
}
// Get the response so that we don't leave this request hanging around
WebResponse response = webRequest.GetResponse();
response.Close();
3 голосов
/ 25 января 2012

Я не знаю, как именно я дошел до этого обходного пути, у меня еще не было времени провести какое-то исследование, так что решать вам, ребята. Есть параметр, и я использовал его следующим образом (в конструкторе моего класса перед созданием экземпляра объекта HTTPWebRequest):

System.Net.ServicePointManager.Expect100Continue = false;

Не знаю почему, но теперь мои звонки выглядят намного быстрее.

3 голосов
/ 26 марта 2010

Используйте компьютер, отличный от localhost , затем используйте WireShark , чтобы увидеть, что действительно происходит по проводу.

Как и другие говорили, это может быть несколько вещей. Взгляд на вещи на уровне TCP должен дать ясную картину.

1 голос
/ 11 октября 2017

Я знаю, что это какой-то старый поток, но я потерял целый день из-за медленного HttpWebRequest, безуспешно пробовал каждое предоставленное решение Каждый запрос на любой адрес длился более одной минуты.

В конце концов, проблема была с моим антивирусным брандмауэром (Eset) . Я использую брандмауэр с интерактивным режимом, но Eset каким-то образом был отключен полностью. Это вызвало просьбу длиться вечно. После включения Eset и выполнения запроса отображается сообщение с подсказкой брандмауэра, а после подтверждения запрос выполняется менее одной секунды .

0 голосов
/ 19 мая 2018

Для меня проблема была в том, что я установил LogMeIn Hamachi - по иронии судьбы, чтобы удаленно отлаживать ту же программу, которая затем начала демонстрировать эту крайнюю медлительность.

К вашему сведению, отключение сетевого адаптера Hamachi было недостаточно, поскольку, похоже, его служба Windows повторно включает адаптер.

Кроме того, повторное подключение к моей сети Hamachi не решило проблему. Только отключение адаптера (путем отключения службы Windows LogMeIn Hamachi) или, возможно, удаление Hamachi, решило проблему для меня.

Можно ли попросить HttpWebRequest выйти через определенный сетевой адаптер?

0 голосов
/ 12 декабря 2016

Это сработало для меня:

<configuration>
  <system.net>
    <defaultProxy erabled="false"/>
  </system.net>
</configuration>

Кредиты: https://social.msdn.microsoft.com/Forums/en-US/14844bfe-ad5b-4e5a-b6ef-4ff9a1a770f8/slow-httpwebrequest-the-first-time-the-program-starts?forum=ncl

0 голосов
/ 11 июня 2016

Я безуспешно перепробовал все описанные здесь решения, звонок занял около 5 минут.

В чем была проблема: Мне нужен был тот же сеанс и, очевидно, те же файлы cookie (запрос сделан на том же сервере), поэтому Я заново создал файлы cookie из Request.Cookies в WebRequest.CookieContainer . Время отклика составляло около 5 минут.

Мое решение: Прокомментировал код, связанный с cookie и bam! Вызов занял менее одной секунды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...