Время ожидания операции истекло в System.Net.HttpWebRequest.GetResponse () при отправке большого количества запросов на хост

Я отправляю большое количество одновременных запросов к определенной веб-службе с разными данными. Для этого я создал несколько потоков (около 50). Общее количество запросов в минуту может увеличиваться до 10000. Приложение в виде службы Windows работает нормально в течение нескольких минут, а затем возникает ошибка тайм-аута операции.

Я пробовал обычные подозрения, такие как увеличение DefaultConnectionLimit, закрытие объекта веб-ответа. Поскольку запросы не занимают много времени на сервере, я также установил для запросов Timeout и ReadWriteTimeout значение 5 секунд. Ниже приведен фрагмент кода, который неоднократно вызывается разными потоками.

// Below line is executed at the start of application
ServicePointManager.DefaultConnectionLimit = 15000;

// Below code is executed at repeatedly by different threads
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Host = hostName;
request.Proxy = null;
request.UserAgent = "Windows Service";
byte[] bytes = new byte[0];
if (body != null)
{
    bytes = System.Text.Encoding.ASCII.GetBytes(body);
    request.ContentType = "text/xml; encoding='utf-8'";
    request.ContentLength = bytes.Length;
}
request.Method = "POST";
request.Timeout = 5000;
request.ReadWriteTimeout = 5000;

request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(username + ":" + password));

request.CookieContainer = this.cookieContainer;

if (body != null)
{
    Stream requestStream = request.GetRequestStream();
    requestStream.Write(bytes, 0, bytes.Length);
    requestStream.Close();
}

HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();

using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
     responseText = streamReader.ReadToEnd();
}
httpResponse.Close();

person pull420    schedule 14.02.2018    source источник
comment
Вы используете http 1.0 или 1.1? Попробуйте установить значение 1.0: request.ProtocolVersion = HttpVersion.Version10; 1.1 - это режим фрагмента, и если вы не отправите следующее сообщение фрагмента, вы получите тайм-аут.   -  person jdweng    schedule 14.02.2018
comment
@FaizanRabbani: -да, я пытался увеличить время ожидания, но это просто замедляет последующие запросы, и ошибка регистрируется после этого периода ожидания. Так что на самом деле нам это не помогает.   -  person pull420    schedule 14.02.2018
comment
@FaizanRabbani: - Нет, это служба Windows.   -  person pull420    schedule 14.02.2018
comment
Вы уверены, что проблема на вашей стороне? Возможно, веб-служба (например) обслуживает только 3 запроса за раз и ставит в очередь остальные?   -  person mjwills    schedule 14.02.2018
comment
Можете ли вы попробовать что-нибудь, что предложил этот пользователь? stackoverflow.com/a/16744521/4222487   -  person FaizanHussainRabbani    schedule 14.02.2018
comment
Я не отправляю 15000 запросов одновременно, но есть ли проблема с установкой этого значения на 15000 вместо 50? Это все равно больше, чем количество одновременных запросов. Я не вижу документации, в которой говорится об этом.   -  person pull420    schedule 14.02.2018
comment
Улучшится, если установить 50? Также обновите свое сообщение, чтобы показать, как вы управляете потоками. Это Parallel.ForEach? Что-то другое?   -  person mjwills    schedule 14.02.2018
comment
Нет, не сейчас......   -  person pull420    schedule 21.02.2018


Ответы (1)


ServicePointManager.DefaultConnectionLimit ограничивает количество исходящих веб-запросов к данному серверу. По умолчанию обычно используется 2 или 10.

Если вы выполняете 50 параллельных вызовов этой веб-службы, вы должны установить для ServicePointManager.DefaultConnectionLimit (при запуске приложения) большее число (например, 40-50).

Кроме того, вы не звоните Close или Dispose на request. Вы должны это сделать, или пусть using позаботится об этом за вас. .

person mjwills    schedule 14.02.2018
comment
Итак, когда вы делаете больше одновременных запросов, чем DefaultConnectionLimit, запросы не просто помещаются в очередь? Могли бы вы таким образом потерять заявку? - person Henk Holterman; 01.03.2019
comment
Да, они в очереди @HenkHolterman. Но если вы поставите в очередь достаточное количество из них, у некоторых начнется тайм-аут (как упоминает OP). Представьте, что вы выполняете 10 000 запросов в минуту, и каждый запрос занимает 10 секунд. Если вы выполняете только 10 запросов за раз (значение этого параметра по умолчанию для веб-приложения), очевидно, что ваша пропускная способность эффективно ограничена до 60 в минуту. Время ожидания у 9 940 из них истечет. - person mjwills; 01.03.2019