Как остановить исходящие HTTP-соединения от тайм-аута - PullRequest
2 голосов
/ 31 мая 2019

Backgound:

В настоящее время я размещаю приложение ASP.NET в Azure со следующими характеристиками:

  • ASP .Net Core 2.2
  • Использование Flurl для HTTP-запросов
  • Kestrel Webserver
  • Docker (Linux - mcr.microsoft.com/dotnet/core/aspnet:2.2 runtime)
  • Служба приложений Azure в плане обслуживания приложений уровня P2V2

У меня есть пара фоновых заданий, которые выполняются в службе, которая выполняет множество исходящих HTTP-вызовов сторонней службе.

Проблема:

При небольшой нагрузке (приблизительно 1 звонок в 10 секунд) все запросы выполняются в течение секунды без проблем. Проблема, с которой я сталкиваюсь, заключается в том, что при большой нагрузке, когда служба может сделать до 3/4 вызовов за 10-секундный промежуток времени, некоторые запросы будут случайным образом прерваны по таймауту и ​​вызовут исключение. Когда я использовал RestSharp, исключение гласило: «Время операции истекло». Теперь, когда я использую Flurl, исключение гласит «Время ожидания истекло».

Вот подсказка: если я запускаю ту же работу на своем ноутбуке под управлением Windows 10 / Visual Studios 2017, эта проблема НЕ возникает. Это заставляет меня верить, что я достигаю некоторого предела или исчерпываю какой-то ресурс в моей размещенной среде. Неясно, относится ли это к соединению / сокету или потоку.

Вещи, которые я пробовал:

  • Убедитесь, что все пути кода к запросу используют async/await для предотвращения блокировки
  • Убедитесь, что Kestrel Defaults разрешает неограниченное количество подключений (по умолчанию)
  • Убедитесь, что ограничения подключения по умолчанию для докеров достаточны (по умолчанию 2000, более чем достаточно)
  • Настройка ServicePointManager настроек для пределов подключения

Вот код в моем файле startup.cs, который я сейчас использую, чтобы попытаться предотвратить эту проблему:

public class Startup
{
    public Startup(IHostingEnvironment hostingEnvironment)
    {
        ...

        // ServicePointManager setup
        ServicePointManager.UseNagleAlgorithm = false;
        ServicePointManager.Expect100Continue = false;
        ServicePointManager.DefaultConnectionLimit = int.MaxValue;
        ServicePointManager.EnableDnsRoundRobin = true;
        ServicePointManager.ReusePort = true;

        // Set Service point timeouts
        var sp = ServicePointManager.FindServicePoint(new Uri("https://placeholder.thirdparty.com"));
        sp.ConnectionLeaseTimeout = 15 * 1000; // 15 seconds  

        FlurlHttp.ConfigureClient("https://placeholder.thirdparty.com", cli => cli.Settings.ConnectionLeaseTimeout = new TimeSpan(0, 0, 15));
    }
}

Кто-нибудь еще сталкивался с подобной проблемой к этому? Я открыт для любых предложений о том, как лучше всего отладить эту ситуацию, или о возможных методах решения проблемы. Я в полной растерянности после исследования этого в течение нескольких дней.

Заранее спасибо.

1 Ответ

3 голосов
/ 05 июня 2019

У меня были похожие проблемы.Взгляните на Ядро Asp.net HttpClient имеет много соединений TIME_WAIT или CLOSE_WAIT .Отладка через netstat помогла выявить проблему для меня.Как одно из возможных решений.Я предлагаю вам использовать IHttpClientFactory.Вы можете получить больше информации от https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2 Это должно быть довольно просто в использовании, как описано в Время жизни клиента Flurl в ASP.Net Core 2.1 и IHttpClientFactory

...