У меня есть настольное приложение C#, которому необходимо сделать несколько одновременных HTTP-запросов на один и тот же веб-сервер. Вот тест я провел, чтобы проверить, действительно ли мои запросы случаются одновременно:Несколько одновременных запросов к одному и тому же http-хосту
На веб-сервере, создал тестовую страницу, которая спит в течение 3-х секунд (имитирует некоторые давно запущенной задачи), а затем возвращает текущую дату/время. Вот код (VB.Net):
<% system.threading.thread.sleep (3000)%> <% =% в настоящее время>
В C# приложение, у меня есть функция MakeRequest (), который использует System.Net.Http.HttpClient для создания веб-запроса и возвращает ответ как строку.
Тогда в # приложение C есть функция вызывается нажатием кнопки, что вызывает MakeRequest() несколько раз асинхронно:
вар ответы = подстерегающие Task.WhenAll (MakeRequest(), MakeRequest(), MakeRequest ());
В приведенном выше примере, MakeRequest() вызывается 3 раза. То, что я вижу на веб-сервере, когда я отслеживаю счетчик запросов/сек, состоит в том, что он получает 2 запроса, а затем через 3 секунды - еще один запрос. Это по дизайну, потому что значение по умолчанию для System.Net.ServicePointManager.DefaultConnectionLimit равно 2, поэтому мое приложение C# может отправлять только по 2 запроса одновременно, хотя я попросил 3. Общее время, когда приложение C# заняло завершение нажатия кнопки 6 сек.
Теперь в приложении C# я устанавливаю ServicePointManager.DefaultConnectionLimit = 1000000. На этот раз запросы/сек на веб-сервере показывают 3, а кнопка щелчка в приложении C# завершается через 3 секунды. Все хорошо до сих пор.
Далее я меняю приложение C# на 60 одновременных вызовов, а не на 3. Вот где вещи становятся интересными. Когда я нажимаю кнопку, я ожидаю увидеть запросы/сек на веб-сервере, чтобы увеличить до 60, а приложение C#, чтобы завершить нажатие кнопки за 3 секунды. То, что я получаю, это веб-сервер Requests/sec, показывающий что-то вроде 5, через 3 секунды еще 5 и т. Д. До тех пор, пока не будут сделаны все 60 запросов. Когда я снова нажимаю кнопку, то же изображение, за исключением Requests/sec spike, до 10 или 15, и щелчок кнопки, очевидно, завершается быстрее. Нажмите еще раз - на этот раз Запросы/сек показывают два всплеска до 30, а нажатие кнопки заканчивается через 6 секунд. Последующие нажатия кнопок приводят к появлению запросов/сек, начиная с 40 до 20 (всего 60 запросов), затем 50 и 10, затем, возможно, 55 и 5, и в конечном итоге мое приложение C# начинает отправлять все 60 запросов за один раз. Нажатие кнопки завершается за 3 секунды, а запросы/сек на веб-сервере показывают один всплеск до 60. Если я продолжаю нажимать кнопку, я последовательно получаю все 60 запросов одновременно.
Но это еще не все. Если я перестаю нажимать кнопку, мое приложение C#, похоже, «забудет» это предыдущее достижение. Я не перезапускаю приложение, просто перестаю нажимать кнопку на минуту, а при следующем нажатии я возвращаюсь к 5 запросам за раз, и описанный выше сценарий повторяется, если я продолжаю постоянно нажимать кнопку.
Я также выполнил вышеуказанный тест из MVC - только что скопировал и вставил код из приложения C# на страницу MVC. Получил точно такой же результат.
Может кто-нибудь объяснить, что происходит?Спасибо
Вот код приложения C#. Это приложение WinForms, а код живет внутри формы класса:
<!-- language: lang-c# -->
private HttpClient _httpClient = new HttpClient();
private async void button1_Click(object sender, EventArgs e)
{
ServicePointManager.DefaultConnectionLimit = 1000000;
var sw = Stopwatch.StartNew();
var responses = await Task.WhenAll(MakeRequest(), MakeRequest(), MakeRequest());
sw.Stop();
var msg = String.Join("\r\n", responses) + "\r\n\r\nTime Elapsed: " + sw.ElapsedMilliseconds;
MessageBox.Show(msg);
}
private async Task<string> MakeRequest()
{
using (var message = await _httpClient.GetAsync("http://TestServer/TestPage.aspx"))
{
return await message.Content.ReadAsStringAsync();
}
}
Благодарим вас за ответ. 1. Да, я столкнулся с этой проблемой, поэтому переместил веб-страницу в IIS на Win Server 2008. На самом деле я попытался запустить страницу MVC, которая отправляет запросы на Server 2008 тоже - тот же результат, что и при запуске с Win 10 2. Не уверен, почему мой клиентский код будет синхронным. Я отправил код в исходный вопрос. Можете ли вы предложить, как мне его изменить? – Andrew
Этот код в порядке. Можете ли вы отправить код, который выполняет 60 запросов одновременно? Пул потоков ASP.NET будет перегружен, кстати, со всеми этими синхронными ожиданиями. Используйте действие async mvc и используйте 'await Task.Delay'. – usr
Код, который выполняет 60 запросов одновременно, совпадает с указанным выше, за исключением строки 'var response = await Task.WhenAll (MakeRequest(), MakeRequest(), MakeRequest());' вы повторяете 'MakeRequest() '60 раз. Что касается переполнения пула потоков ASP.Net, я не думаю, что это происходит, потому что когда мое клиентское приложение отправляет одновременно 60 запросов одновременно, веб-сервер успешно обрабатывает их все одновременно. Проверьте здесь: [link] (https://msdn.microsoft.com/en-us/library/ee377050 (v = bts.10) .aspx), раздел «Настройка ASP.NET 4 MaxConcurrentRequests для IIS 7.5/7.0 Интегрированный режим « – Andrew