Как предотвратить истечение времени ожидания исходящих HTTP-соединений

Фон:

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

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

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

Проблема:

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

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

Что я пробовал:

  • Убедитесь, что все пути кода к запросу используют async/await для предотвращения блокировок
  • Убедитесь, что настройки Kestrel по умолчанию разрешают неограниченное количество подключений (по умолчанию)
  • Убедитесь, что лимиты подключений Dockers по умолчанию достаточны (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));
    }
}

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

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


person DankMetalSounds    schedule 30.05.2019    source источник


Ответы (1)


У меня были похожие проблемы. Взгляните на Asp.net Core 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

person Ahmet    schedule 05.06.2019