У меня есть проект веб-API ASP.NET Core. У этого есть один контроллер с методом GetLocations.
GetLocations подключается к 5 другим веб-службам в Интернете. Собирает информацию и возвращает коллекцию через json. В этом методе я кэширую данные каждые 5 минут, используя кеширование в памяти.
Если срок действия кеша истекает, он пытается подключиться ко всем 5 службам, получить информацию и так далее.
Моя проблема:
У меня много пользователей, которые постоянно запрашивают эти данные, 50 запросов в секунду к этому API.
Когда истекает срок действия кеша, я считаю, что есть какая-то блокировка потока. На данный момент у меня ограниченная видимость проекта, но я подозреваю, что все эти запросы вызывают метод и обращаются к 5 зависимым службам, пока одна из них не получит завершенный ответ от всех 5.
Верно ли мое предположение? Если да, то как я могу это исправить? Нужно ли будет выполнять каждый вызов веб-служб асинхронно? Поможет ли это в этом сценарии? Я не уверен на 100%, потому что запросы - это то, что запускает вызов метода.
Было бы здорово, если бы вы могли предоставить минимальный воспроизводимый пример.
При обновлении я бы создал временный кеш, который, когда он будет скопирован в действующую систему, будет работать медленно в течение очень короткого времени.





Вы обязательно должны выполнять вызовы внешних служб с использованием Async / Await.
Это просто данность - лучше всего всегда использовать асинхронный режим для тяжелых операций ввода-вывода (таких как вызов сторонней службы).
Теперь вы также должны создать класс, который управляет этими вызовами. Вы можете добавить его как Singleton в свой IoCConfig. В этом классе убедитесь, что вы «блокируете», чтобы избежать проблемы, которую вы только что описали, и не вызывайте базовые службы несколько раз во время создания кеша.
Проверить здесь: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement
«всегда использовать асинхронный режим для тяжелых операций ввода-вывода» --- асинхронный режим не является бесплатным, у вас могут быть случаи, когда блокирование ввода-вывода предпочтительнее из-за требований к производительности. Я согласен с тем, что в целом async может быть выбором по умолчанию, я считаю, что «всегда» здесь сильное слово.
Вы столкнулись с этой проблемой по следующей причине.
Решение этого.
Примечание: должно получиться что-то вроде этого.
public List<string> GetData()
{
if (Cache[key] == null)
{
lock(obj) // obj should be static
{
if (Cache[key] == null)
{
// Load data from service
Cache[key] == data;
}
}
}
return (List<string>)Cache[Key];
}
"Верно ли мое предположение?" --- учитывая, что вы буквально ничего не предоставили, это может быть с равной вероятностью: Да / Нет / Может быть.