Стратегии "предварительного прогревания" кэша ASP.NET

У меня есть веб-приложение ASP.NET MVC 3/.NET, которое сильно зависит от данных, в основном вокруг концепции "Местоположения" (Нью-Йорк, Калифорния и т.д.).

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

например:

public ICollection<Location> FindXForX(string x)
{
   var result = _cache.Get(x.ToKey()) as Locaiton; // try cache

   if (result == null) {
      result = _repo.Get(x.ToKey()); // call db
      _cache.Add(x.ToKey(), result); // add to cache
   }

   return result;
}

Но я не хочу, чтобы первый неудачный первый пользователь ожидал этого вызова базы данных.

Вызов базы данных может занимать от 40 до 60 секунд, что значительно превышает тайм-аут по умолчанию для запроса ASP.NET.

Я хочу "предварительно нагревать" эти вызовы для определенных "популярных" местоположений (например, в Нью-Йорке, Калифорния), когда мое приложение запускается или вскоре после этого.

Я не хочу просто делать это в Глобальном asax (Application_Start), потому что для запуска приложения потребуется слишком много времени. (я планирую предварительно кэшировать около 15 местоположений, так что несколько минут работы).

Можно ли каким-то образом отключить эту логику асинхронно? Может быть, услуга на стороне - лучший вариант?

Единственная альтернатива, о которой я могу думать, - это страница администратора, у которой есть кнопки для этих действий. Таким образом, администратор (например, я) может запустить эти запросы после запуска приложения. Это было бы самым простым решением.

Любые советы?

Ответ 1

Быстрый и грязный способ заключается в отключении Task от Application_Start

Но я обнаружил, что приятно включить эту функциональность в небольшую инфраструктуру, чтобы вы могли создать страницу ~/Admin/CacheInfo, чтобы вы могли отслеживать прогресс, состояние и исключения, которые могут находиться в процессе загрузка кеша.

Ответ 2

Посмотрите "Всегда работает" для настройки IIS 7.5. Что это в основном делает, так это иметь готовый пул приложений, когда существующий должен быть переработан. Конечно, самый первый займет 40-60 секунд, но потом все будет быстро, если вы физически не перезагрузите машину.

Ответ 3

Прежде чем начать кеширование, я предлагаю вам проверить, что запрос "так быстро, как может быть", сначала посмотрев, сколько логических считываний он делает.

Ответ 4

Похоже, вы должны просто сбрасывать результаты в отдельной таблице и иметь запланированную задачу для периодической репопуляции этой таблицы.

Если одна предварительно вычисленная таблица недостаточна, потому что она заканчивается слишком большим количеством данных, которые вам нужно выполнить, вы можете использовать более одного.

Ответ 5

Одним из решений является запустить рабочий поток в методе Application_Start, который выполняет предварительное прогревание в фоновом режиме. Если вы все сделаете правильно, ваше приложение не займет больше времени, потому что поток будет выполняться асинхронно.

Ответ 6

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

Ответ 7

Выполнение загрузки в Task из Application_Start - это способ, как упоминал Скотт.

Просто будьте осторожны - если ваш сайт перезагрузится, а 10 человек попытаются просмотреть Калифорнию, вы не захотите, чтобы в итоге 10 экземпляров _repo.Get(x.ToKey()); // call db пытались загрузить одни и те же данные.

Может быть хорошей идеей сохранить логическое значение "IsPreloading" в состоянии приложения. Установите его в true в начале вашей функции предварительной загрузки и false в конце. Если значение установлено, убедитесь, что вы не загрузили ни одно из 15 предварительно загруженных мест в FindXForX.

Ответ 8

Предлагаю взглянуть на автозапуск вашего приложения, особенно если вы балансируете нагрузку.