HttpClient - задача была отменена - Как получить точное сообщение об ошибке?
У меня есть следующий тестовый код. Я всегда получаю ошибку "Задача была отменена" после цикла 316934 или 361992 раз.
Если я не ошибаюсь, есть две возможные причины, по которым задача была отменена. a) HttpClient получил таймаут или b) слишком много задач в очереди, а некоторые задачи получили тайм-аут.
Я не смог найти документацию об ограничении в очередности задач. И я попытался создать более 500 тыс. Задач и без тайм-аута. Думаю, причина "b" может быть неправильной.
Q1. Есть ли еще одна причина, по которой я пропустил?
Q2. Если это из-за таймаута HttpClient, как я могу получить точное сообщение исключения вместо исключения TaskCancellation.
Q3. Какой был бы лучший способ исправить это? Должен ли я ввести дроссель?
Спасибо!
var _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", "ISO-8859-1");
int[] intArray = Enumerable.Range(0, 600000).ToArray();
var results = intArray
.Select(async t => {
using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, "http://www.google.com")) {
log.Info(t);
try {
var response = await _httpClient.SendAsync(requestMessage);
var responseContent = await response.Content.ReadAsStringAsync();
return responseContent;
}
catch (Exception ex) {
log.ErrorException(string.Format("SoeHtike {0}", Task.CurrentId), ex);
}
return null;
}
});
Task.WaitAll(results.ToArray());
Console.ReadLine();
Ниже приведен шаг к репликации проблемы.
-
Создайте проект консоли в VS 2012.
-
Скопируйте и вставьте мой код в Main.
-
Поместите точку останова в этой строке "log.ErrorException(string.Format(" SoeHtike
{0}",
Task.CurrentId),
ех); "
Запустите программу в режиме отладки. Подождите несколько минут. (может быть, 5 минут?) Я только что проверил свой код, и я получил исключение через 3 минуты. Если у вас есть скрипач, вы можете отслеживать запросы, чтобы вы знали, что программа все еще работает или нет.
Не стесняйтесь, дайте мне знать, если вы не можете воспроизвести проблему.
Ответы
Ответ 1
Значение по умолчанию HttpClient.Timeout
равно 100 секундам (00:01:40). Если вы сделаете отметку времени в своем блоке catch
, вы заметите, что задачи начнут отменяться точно в это время. По-видимому, существует ограниченное количество HTTP-запросов, которые вы можете делать в секунду, а другие - в очереди. Запросы в очереди отправляются в таймаут. Из всех 600 тыс. Задач я лично получил только 2500 успешных, другие были отменены.
Я также считаю маловероятным, что вы сможете запустить всего 600 000 задач. Многие сетевые драйверы пропускают большое количество запросов только в течение небольшого времени и через некоторое время сокращают это число до очень низкого значения. Моя сетевая карта позволила мне отправить всего 921 запрос в течение 36 секунд и опустила эту скорость только на один запрос в секунду. На этой скорости для выполнения всех задач потребуется неделя.
Если вы можете обойти это ограничение, убедитесь, что вы создаете код для 64-битной платформы, так как приложение очень голодно для памяти.
Ответ 2
Не используйте экземпляр HttpClient, который вы используете. Странно, но исправил для меня эту проблему.
Ответ 3
просто хотел поделиться
У меня был аналогичный код для загрузки тестов на наши серверы, и его высокая вероятность того, что ваши запросы будут отключены.
Вы можете установить тайм-аут для вашего HTTP-запроса max и посмотреть, не изменит ли он что-либо для вас.
Я попытался поразить наши серверы, создав различные потоки. И это увеличило количество просмотров, но все они в конечном итоге истекут время. И также вы не можете установить тайм-аут при попадании в другой поток.