У меня есть довольно простой веб-API, который использует инфраструктуру сущностей для доступа к серверной части SQL.Код API просто передает запросы некоторым хранимым процессам и возвращает данные;ничего особенного.Я использую .net 4.6 (ограничен, потому что я работаю на стандарт Win 2008).Я НЕ использую async / await, потому что меня снова ограничивает старая библиотека журналов, которая не поддерживает этот шаблон.
Я запускаю пакетный тест, в котором я создаю 30 потоков, которые одновременно вызывают одну конечную точку API.Каждый поток будет ждать одну секунду между вызовами.Это создает нагрузку около 20 запросов в секунду.
Когда я запускаю тест, производительность в порядке.Звонки возвращаются в течение <50 мс.Затем, примерно через две минуты (всегда примерно в одно и то же время), asp.net начнет ставить запросы в очередь (в зависимости от производительности), а затем внезапно IIS просто зависнет, и я получу тайм-ауты.Процессор увеличится до 99 процентов, что странно, потому что весь мой код асинхронен и ожидает вызовов БД.Производительность не ухудшается, как в большинстве случаев.Это нормально и быстро, пока вдруг это не так. </p>
Я не получаю никаких ошибок из моего кода.Ничего полезного в журнале событий.У меня есть все настройки IIS по умолчанию, за исключением того, что я изменил предел очереди http.sys с 1000 на 5000 после прочтения этой рекомендации где-то еще, но это не помогло.
Любые предложения о том, что я могу попробовать или посмотретьили делать?Я вроде как в тупик.
РЕДАКТИРОВАТЬ: неправильно сказал, что я использую async / await.Не я.
Вот код, минус назначение переменной и другой не относящийся к делу код.Вызов api входит в метод top, затем второй, затем третий
[HttpGet]
[Route("productvariantassociationids")]
public LocatorServiceOutputModel GetProductVariantAssociationIds([FromUri]ProductVariantInput input)
{
var output = ProductService.GetProductVariantAssociationIds(input);
if ((output == null) || (output.Data == null) || (((List<int>)output.Data).Count == 0))
throw new HttpResponseException(System.Net.HttpStatusCode.NotFound);
return output;
}
public LocatorServiceOutputModel GetProductVariantAssociations(ProductVariantInput input)
{
var output = new LocatorServiceOutputModel();
var cachedData = CacheService.Get<List<ProductVariantAssociation>>(input.ToString());
if (cachedData != null)
{
output.Data = cachedData;
output.FromCache = true;
}
else
{
var associations = ProductRepository.GetProductVariantAssociations(input.ProductLineTypeID, input.ProductVersionTypeID, input.FormCodeTypeID, input.PremiumStructureTypeID,
input.DefinitionOfDisabilityTypeID, input.StateTypeID, input.ApplicationDate, input.InsurredAge);
var mappedAssociations = Mapper.Map<List<ProductVariantAssociation>>(associations);
CacheService.Set(input.ToString(), mappedAssociations);
output.Data = mappedAssociations;
}
output.Success = true;
return output;
}
public List<DBRiderBenefit> GetRiderBenefits(int? productVariantAssociationID = null, StateTypeEnum? stateTypeID = null, int? insurredAge = null, DefinitionOfDisabilityTypeEnum? definitionOfDisabilityType = null,
EliminationPeriodTypeEnum? eliminationPeriodTypeID = null, BenefitPeriodTypeEnum? benefitPeriodTypeID = null, MentalSubstanceLimitationEnum? mentalSubstanceLimitationID = null,
OccupationClassTypeEnum? occupationClassTypeID = null, OccupationGroupTypeEnum? occupationGroupTypeID = null, string occupationTypeValueText = null,
bool? isExercise = null, string callingSystemID = null, int? productVersionRevisionId = null)
{
using (ProductLibraryContext context = new ProductLibraryContext())
{
List<DBRiderBenefit> results = null;
if (productVersionRevisionId != null)
{
results = context.Database.SqlQuery<DBRiderBenefit>("exec [USP_ProductLibrary_Get_RiderBenefit] @ProductVariantAssociationID, @StateTypeID, @IssuredAge, @DefinitionOfDisabilityID, @EliminationPeriodTypeID, @BenefitPeriodTypeID, @MentalSubstanceLimitationID, @OccupationClassTypeID, @OccupationGroupTypeID, @OccupationType_ValueText, @IsExercise, @CallingSystemId, @ProductVersionRevision"
, paramProductVariantAssociationID, paramStateTypeID, paramInsuredAge, paramDefinitionOfDisabilityID, paramEliminationPeriodTypeID, paramBenefitPeriodTypeID
, paramMentalSubstanceLimitationID, paramOccupationClassTypeID, paramOccupationGroupTypeID, paramOccupationTypeValueText, paramIsExercise, paramCallingSystemId, paramProductVersionRevision).ToList();
}
else
{
results = context.Database.SqlQuery<DBRiderBenefit>("exec [USP_ProductLibrary_Get_RiderBenefit] @ProductVariantAssociationID, @StateTypeID, @IssuredAge, @DefinitionOfDisabilityID, @EliminationPeriodTypeID, @BenefitPeriodTypeID, @MentalSubstanceLimitationID, @OccupationClassTypeID, @OccupationGroupTypeID, @OccupationType_ValueText, @IsExercise, @CallingSystemId"
, paramProductVariantAssociationID, paramStateTypeID, paramInsuredAge, paramDefinitionOfDisabilityID, paramEliminationPeriodTypeID, paramBenefitPeriodTypeID
, paramMentalSubstanceLimitationID, paramOccupationClassTypeID, paramOccupationGroupTypeID, paramOccupationTypeValueText, paramIsExercise, paramCallingSystemId).ToList();
}
return results;
}
}