Фон:
В настоящее время я размещаю приложение 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));
}
}
Кто-нибудь еще сталкивался с подобной проблемой? Я открыт для любых предложений о том, как лучше всего отладить эту ситуацию или возможных методах решения проблемы. Я в полной растерянности после того, как исследовал это в течение нескольких дней.
Заранее спасибо.