Я использую static Lazy<HttpClient>
, что должно обеспечить повторное использование сокетов. ( Вы неправильно используете HttpClient, и это может привести к дестабилизации программного обеспечения )
Однако мое приложение зависает после нескольких сотен запросов. Я добавил ведение журнала трассировки и мог воспроизвести проблему в действии MVC, которое ничего не делает *, кроме вызова HttpClient.
- Для явного выражения он читает значение web.config, проверяет некоторые ViewModel значения и анализирует ответ HttpClient, но он никогда не приходит.
netstat
показывает, что существует много открытых сокетов. Даже сейчас, спустя несколько минут, после того как я остановил запросы и потратил некоторое время на написание этого вопроса, количество сокетов, похоже, не уменьшилось.
C:\Users\me>netstat
Active Connections
Proto Local Address Foreign Address State
TCP 127.0.0.1:443 localhost:53730 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53731 TIME_WAIT
TCP 127.0.0.1:443 localhost:53732 TIME_WAIT
TCP 127.0.0.1:443 localhost:53733 TIME_WAIT
TCP 127.0.0.1:443 localhost:53734 TIME_WAIT
TCP 127.0.0.1:443 localhost:53736 TIME_WAIT
TCP 127.0.0.1:443 localhost:53737 TIME_WAIT
TCP 127.0.0.1:443 localhost:53738 TIME_WAIT
TCP 127.0.0.1:443 localhost:53739 TIME_WAIT
TCP 127.0.0.1:443 localhost:53740 TIME_WAIT
TCP 127.0.0.1:443 localhost:53741 TIME_WAIT
TCP 127.0.0.1:443 localhost:53743 TIME_WAIT
TCP 127.0.0.1:443 localhost:53751 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53752 TIME_WAIT
TCP 127.0.0.1:443 localhost:53753 TIME_WAIT
TCP 127.0.0.1:443 localhost:53754 TIME_WAIT
TCP 127.0.0.1:443 localhost:53755 TIME_WAIT
TCP 127.0.0.1:443 localhost:53760 TIME_WAIT
TCP 127.0.0.1:443 localhost:53765 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53766 TIME_WAIT
TCP 127.0.0.1:443 localhost:53767 TIME_WAIT
TCP 127.0.0.1:443 localhost:53768 TIME_WAIT
TCP 127.0.0.1:443 localhost:53769 TIME_WAIT
TCP 127.0.0.1:443 localhost:53773 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53776 TIME_WAIT
TCP 127.0.0.1:443 localhost:53777 TIME_WAIT
TCP 127.0.0.1:443 localhost:53778 TIME_WAIT
TCP 127.0.0.1:443 localhost:53779 TIME_WAIT
TCP 127.0.0.1:443 localhost:53780 TIME_WAIT
TCP 127.0.0.1:443 localhost:53784 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53787 TIME_WAIT
TCP 127.0.0.1:443 localhost:53788 TIME_WAIT
TCP 127.0.0.1:443 localhost:53789 TIME_WAIT
TCP 127.0.0.1:443 localhost:53790 TIME_WAIT
TCP 127.0.0.1:443 localhost:53791 TIME_WAIT
TCP 127.0.0.1:443 localhost:53795 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53798 TIME_WAIT
TCP 127.0.0.1:443 localhost:53799 TIME_WAIT
TCP 127.0.0.1:443 localhost:53800 TIME_WAIT
TCP 127.0.0.1:443 localhost:53801 TIME_WAIT
TCP 127.0.0.1:443 localhost:53802 TIME_WAIT
TCP 127.0.0.1:443 localhost:53806 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53808 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53809 TIME_WAIT
TCP 127.0.0.1:443 localhost:53810 TIME_WAIT
TCP 127.0.0.1:443 localhost:53811 ESTABLISHED
TCP 127.0.0.1:443 localhost:53812 ESTABLISHED
TCP 127.0.0.1:443 localhost:53813 ESTABLISHED
TCP 127.0.0.1:443 localhost:53814 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53815 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53816 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53817 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53818 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53819 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53820 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53821 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53822 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53823 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53824 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53825 CLOSE_WAIT
TCP 127.0.0.1:443 localhost:53851 ESTABLISHED
TCP 127.0.0.1:443 localhost:53852 ESTABLISHED
TCP 127.0.0.1:443 localhost:53853 ESTABLISHED
TCP 127.0.0.1:443 localhost:53854 ESTABLISHED
TCP 127.0.0.1:443 localhost:53855 ESTABLISHED
TCP 127.0.0.1:443 localhost:53856 ESTABLISHED
TCP 127.0.0.1:443 localhost:53857 ESTABLISHED
TCP 127.0.0.1:443 localhost:53858 ESTABLISHED
TCP 127.0.0.1:443 localhost:53859 ESTABLISHED
TCP 127.0.0.1:443 localhost:53860 ESTABLISHED
TCP 127.0.0.1:443 localhost:53861 ESTABLISHED
TCP 127.0.0.1:443 localhost:53862 ESTABLISHED
TCP 127.0.0.1:443 localhost:53863 ESTABLISHED
TCP 127.0.0.1:443 localhost:53864 ESTABLISHED
TCP 127.0.0.1:443 localhost:53865 ESTABLISHED
TCP 127.0.0.1:443 localhost:53866 ESTABLISHED
TCP 127.0.0.1:443 localhost:53867 ESTABLISHED
TCP 127.0.0.1:443 localhost:53868 ESTABLISHED
TCP 127.0.0.1:443 localhost:53869 ESTABLISHED
TCP 127.0.0.1:443 localhost:53870 ESTABLISHED
TCP 127.0.0.1:44117 localhost:53301 ESTABLISHED
TCP 127.0.0.1:44117 localhost:53838 ESTABLISHED
TCP 127.0.0.1:44117 localhost:53839 ESTABLISHED
TCP 127.0.0.1:44117 localhost:53840 ESTABLISHED
TCP 127.0.0.1:44117 localhost:53841 ESTABLISHED
TCP 127.0.0.1:44117 localhost:53842 ESTABLISHED
TCP 127.0.0.1:49676 localhost:49677 ESTABLISHED
TCP 127.0.0.1:49677 localhost:49676 ESTABLISHED
TCP 127.0.0.1:50498 localhost:50501 ESTABLISHED
TCP 127.0.0.1:50501 localhost:50498 ESTABLISHED
TCP 127.0.0.1:53301 localhost:44117 ESTABLISHED
TCP 127.0.0.1:53697 localhost:53698 ESTABLISHED
TCP 127.0.0.1:53698 localhost:53697 ESTABLISHED
TCP 127.0.0.1:53699 localhost:53700 ESTABLISHED
TCP 127.0.0.1:53700 localhost:53699 ESTABLISHED
TCP 127.0.0.1:53701 localhost:53702 ESTABLISHED
TCP 127.0.0.1:53702 localhost:53701 ESTABLISHED
TCP 127.0.0.1:53703 localhost:53704 ESTABLISHED
TCP 127.0.0.1:53704 localhost:53703 ESTABLISHED
TCP 127.0.0.1:53705 localhost:53706 ESTABLISHED
TCP 127.0.0.1:53706 localhost:53705 ESTABLISHED
TCP 127.0.0.1:53707 localhost:53708 ESTABLISHED
TCP 127.0.0.1:53708 localhost:53707 ESTABLISHED
TCP 127.0.0.1:53709 localhost:53710 ESTABLISHED
TCP 127.0.0.1:53710 localhost:53709 ESTABLISHED
TCP 127.0.0.1:53711 localhost:53712 ESTABLISHED
TCP 127.0.0.1:53712 localhost:53711 ESTABLISHED
TCP 127.0.0.1:53713 localhost:53714 ESTABLISHED
TCP 127.0.0.1:53714 localhost:53713 ESTABLISHED
TCP 127.0.0.1:53715 localhost:53716 ESTABLISHED
TCP 127.0.0.1:53716 localhost:53715 ESTABLISHED
TCP 127.0.0.1:53717 localhost:53718 ESTABLISHED
TCP 127.0.0.1:53718 localhost:53717 ESTABLISHED
TCP 127.0.0.1:53719 localhost:53720 ESTABLISHED
TCP 127.0.0.1:53720 localhost:53719 ESTABLISHED
TCP 127.0.0.1:53721 localhost:53722 ESTABLISHED
TCP 127.0.0.1:53722 localhost:53721 ESTABLISHED
TCP 127.0.0.1:53723 localhost:53724 ESTABLISHED
TCP 127.0.0.1:53724 localhost:53723 ESTABLISHED
TCP 127.0.0.1:53725 localhost:53726 ESTABLISHED
TCP 127.0.0.1:53726 localhost:53725 ESTABLISHED
TCP 127.0.0.1:53727 localhost:53728 ESTABLISHED
TCP 127.0.0.1:53728 localhost:53727 ESTABLISHED
TCP 127.0.0.1:53730 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53735 localhost:https TIME_WAIT
TCP 127.0.0.1:53742 localhost:https TIME_WAIT
TCP 127.0.0.1:53744 localhost:https TIME_WAIT
TCP 127.0.0.1:53745 localhost:https TIME_WAIT
TCP 127.0.0.1:53746 localhost:https TIME_WAIT
TCP 127.0.0.1:53747 localhost:https TIME_WAIT
TCP 127.0.0.1:53748 localhost:https TIME_WAIT
TCP 127.0.0.1:53749 localhost:https TIME_WAIT
TCP 127.0.0.1:53750 localhost:https TIME_WAIT
TCP 127.0.0.1:53751 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53758 localhost:https TIME_WAIT
TCP 127.0.0.1:53761 localhost:https TIME_WAIT
TCP 127.0.0.1:53762 localhost:https TIME_WAIT
TCP 127.0.0.1:53763 localhost:https TIME_WAIT
TCP 127.0.0.1:53765 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53770 localhost:https TIME_WAIT
TCP 127.0.0.1:53771 localhost:https TIME_WAIT
TCP 127.0.0.1:53772 localhost:https TIME_WAIT
TCP 127.0.0.1:53773 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53775 localhost:https TIME_WAIT
TCP 127.0.0.1:53781 localhost:https TIME_WAIT
TCP 127.0.0.1:53782 localhost:https TIME_WAIT
TCP 127.0.0.1:53783 localhost:https TIME_WAIT
TCP 127.0.0.1:53784 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53786 localhost:https TIME_WAIT
TCP 127.0.0.1:53792 localhost:https TIME_WAIT
TCP 127.0.0.1:53793 localhost:https TIME_WAIT
TCP 127.0.0.1:53794 localhost:https TIME_WAIT
TCP 127.0.0.1:53795 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53797 localhost:https TIME_WAIT
TCP 127.0.0.1:53803 localhost:https TIME_WAIT
TCP 127.0.0.1:53804 localhost:https TIME_WAIT
TCP 127.0.0.1:53805 localhost:https TIME_WAIT
TCP 127.0.0.1:53806 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53808 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53811 localhost:https ESTABLISHED
TCP 127.0.0.1:53812 localhost:https ESTABLISHED
TCP 127.0.0.1:53813 localhost:https ESTABLISHED
TCP 127.0.0.1:53814 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53815 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53816 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53817 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53818 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53819 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53820 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53821 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53822 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53823 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53824 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53825 localhost:https FIN_WAIT_2
TCP 127.0.0.1:53838 localhost:44117 ESTABLISHED
TCP 127.0.0.1:53839 localhost:44117 ESTABLISHED
TCP 127.0.0.1:53840 localhost:44117 ESTABLISHED
TCP 127.0.0.1:53841 localhost:44117 ESTABLISHED
TCP 127.0.0.1:53842 localhost:44117 ESTABLISHED
TCP 127.0.0.1:53851 localhost:https ESTABLISHED
TCP 127.0.0.1:53852 localhost:https ESTABLISHED
TCP 127.0.0.1:53853 localhost:https ESTABLISHED
TCP 127.0.0.1:53854 localhost:https ESTABLISHED
TCP 127.0.0.1:53855 localhost:https ESTABLISHED
TCP 127.0.0.1:53856 localhost:https ESTABLISHED
TCP 127.0.0.1:53857 localhost:https ESTABLISHED
TCP 127.0.0.1:53858 localhost:https ESTABLISHED
TCP 127.0.0.1:53859 localhost:https ESTABLISHED
TCP 127.0.0.1:53860 localhost:https ESTABLISHED
TCP 127.0.0.1:53861 localhost:https ESTABLISHED
TCP 127.0.0.1:53862 localhost:https ESTABLISHED
TCP 127.0.0.1:53863 localhost:https ESTABLISHED
TCP 127.0.0.1:53864 localhost:https ESTABLISHED
TCP 127.0.0.1:53865 localhost:https ESTABLISHED
TCP 127.0.0.1:53866 localhost:https ESTABLISHED
TCP 127.0.0.1:53867 localhost:https ESTABLISHED
TCP 127.0.0.1:53868 localhost:https ESTABLISHED
TCP 127.0.0.1:53869 localhost:https ESTABLISHED
TCP 127.0.0.1:53870 localhost:https ESTABLISHED
snip
У меня есть два вхождения HttpClient, оба с отдельный BaseAddress
. Я попытался заменить HttpClient на Easy.Common.RestClient, но безрезультатно.
Я установил
var servicePoint = ServicePointManager.FindServicePoint(new Uri(webApiAddress));
servicePoint.ConnectionLeaseTimeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;
, но это тоже не помогает. Я установил тайм-аут на 15 секунд. Я пытался установить CloseConnection=true
или установить заголовок "Connection":"Close"
Я не знаю, что еще попробовать ... Может кто-нибудь дать руководство?
Обновление
Давайте go в деталях. У меня есть static Lazy<HttpClient>
в библиотеке классов, внутри класса MyClientWrapper
(пример). Мое приложение Asp. Net MVC 5 включает эту библиотеку классов и создает экземпляр MyClientWrapper
.
Мой MVC контроллер звонит _myClientWrapper.GetData()
. Внутри GetData
создается HttpRequestMessage
, отправляемое в мой API с использованием HttpClient
. HttpResponseMessage
читается. И запрос, и ответ удаляются, и данные возвращаются с GetData
.
Я использую Gatling для отправки 20 запросов для 20 пользователей на MyController/MyAction
. В какой-то момент (иногда раньше, иногда позже) запросы к API больше не поступают. Установка точки останова отладки в MyController
показывает, что GetData()
поражен. Вызов await
принят, и все. netstat
заполняется.
Я пытался устранить проблему.
Сценарий 1: пинг API с помощью PostMan (до того, как что-нибудь зависло от меня). Нет проблем.
Сценарий 2: Удалить весь код из GetData()
и заменить на return somedummydata
.
public async Task<Data> GetData()
{
// No call to HttpClient, no issues
return new Data();
}
Сценарий 3: В GetData()
, просто пропингуйте API, используя HttpClient
, ничего больше и все еще возвращайте некоторые фиктивные данные. Проблема возникает После нескольких пингов ничто больше не достигает API. Переход по MyController
показывает, что вызов GetData
выполнен, но он не проходит. После того, как все застыло, я не могу пропинговать API с помощью PostMan. Ничего не происходит (логирование трассировки Application_BeginRequest
в API не отображается, поэтому API даже не достигается ..)
public async Task<Data> GetData()
{
// Issue occurs as soon as HttpClient is used for GET or POST. In this example, GET.
await _client.GetAsync("pseudocode/Ping");
// In reality I properly HttpRequestMessage/HttpResponseMessage read and dispose, this is just pseudocode really...
return new Data();
}
Обновление
- Изменение
HttpClient
с static
на PerThread
(Castle Windsor Io C) не имеет значения - Интересно, что при каждом зависании происходит ровно три запроса в IIS под WorkerProcesses. Каждый раз. Ровно три. Может ли это иметь какое-либо отношение к максимальному количеству соединений (по умолчанию 2), которое имеет HttpClient?
- Я убедился, что у метода
ping
моего API нет логики c внутри. Это не так.
Обновление
Возможно, связано: HTTP-соединение простаивает, а затем истекает время ожидания при запуске большего количества HttpClient.GetAsyn c () параллельные задачи, чем ServicePointManager.DefaultConnectionLimit