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