Проблема с многопоточностью в ASP.NET Core - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть проект ASP.NET Core Web API.Он имеет один контроллер с методом GetLocations

. GetLocations подключается к 5 другим веб-службам в Интернете.Собирает некоторую информацию и возвращает коллекцию через json.В этом методе я кеширую данные каждые 5 минут, используя кеширование в памяти.

Если срок действия кэша истекает, он пытается подключиться ко всем 5 службам и получить информацию и т. Д.

Моя проблема:

У меня много пользователей, запрашивающихэти данные постоянно, 50 запросов в секунду к этому API.

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

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

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Вы столкнулись с этой проблемой по следующей причине.

  1. Вы используете Cache, и срок его действия истекает в определенное время.
  2. После истечения срока действия Cache вы вызываете метод внешней веб-службысобирать данные.Теперь в этот момент может случиться так, что другой запрос в очереди будет выбран для выполнения.
  3. Как только этот другой запрос выбран для выполнения, он также заканчивает проверку кеша, и теперь данные в кеше выполняют внешнюю службу и т. Д. Для другого запроса.

Решение этого.

  1. Кэш первой проверки содержит данные или нет.
  2. Если не создавать блокировку, поэтому следующий раздел будет выполняться только одним потоком.
  3. Теперь в этом разделе блокировки снова проверьтедля кеша, и если кеш содержит данные, то просто возвращает, но не содержит, а затем вызывает внешнюю службу.
  4. В этот момент, если для выполнения выбран другой поток, он должен ждать, пока секция execlsive завершит свою работу..
  5. Как только этот раздел завершен, он сохраняет данные в кеше, а затем, если появляется какой-либо очередной или новый запрос, он выбирает данные из кеша.

Примечание: должно получиться что-то вроде этого.

    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]; 
     }
0 голосов
/ 14 ноября 2018

Вы должны определенно делать вызовы во внешние службы, используя Async / Await.

Это просто само собой разумеющееся, так как рекомендуется всегда использовать асинхронность для тяжелых операций ввода-вывода (таких как вызов третьего-party service).

Теперь вы также должны создать класс, который управляет этими вызовами.Вы можете добавить его как Singleton в свой IoCConfig.В этом классе убедитесь, что вы «блокируете», чтобы избежать проблемы, которую вы только что описали, и не вызывайте базовые службы несколько раз во время построения кэша.

Проверьте здесь: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...