Stati c HttpClient, но все еще слишком много открытых сокетов - PullRequest
1 голос
/ 10 апреля 2020

Я использую 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

...