Подтвердить что ты не робот

Когда Asp.Net удаляет устаревшие элементы кэша?

Когда вы добавляете элемент в System.Web.Caching.Cache с абсолютной датой истечения срока действия, как в следующем примере, как ведет себя Asp.Net? Это:

  • Просто отметьте элемент как истек, затем выполните CacheItemRemovedCallback при следующей попытке доступа?

  • Удалить элемент из кеша и немедленно выполнить CacheItemRemovedCallback?

    HttpRuntime.Cache.Insert(key,
                             new object(),
                             null, 
                             DateTime.Now.AddSeconds(seconds), 
                             Cache.NoSlidingExpiration,
                             CacheItemPriority.NotRemovable, 
                             OnCacheRemove);
    

MSDN указывает, что это происходит немедленно. Например, раздел "Истечение срока действия" "Обзор кэширования ASP.NET" говорит: "ASP.NET автоматически удаляет элементы из кеша, когда они истекает". Аналогично, пример из раздела "Как уведомлять приложение при удалении элемента из кэша" говорит "Если более 15 секунд проходит между вызовами GetReport [метод в примере], ASP.NET удаляет отчет из кэша."

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

Тем не менее, мой тест был быстрым и грязным, и в комментариях к моему ответу на Есть ли способ запускать процесс каждый день в веб-приложении .NET без написания окон служба или SQL-сервер, кто-то предположил, что Asp.Net фактически отменяет удаление и выполнение обратного вызова, пока что-то не попытается снова получить кэш.

Может ли кто-нибудь урегулировать это авторитетно или это просто рассматривается как деталь реализации?

4b9b3361

Ответ 1

Ура для Reflector!

Истекшие элементы кэша фактически удаляются (и вызываемые вызовы), если:

1) Что-то пытается получить доступ к элементу кэша.

2) Метод ExpiresBucket.FlushExpiredItems запускается и переходит к элементу. Этот метод жестко закодирован для выполнения каждые 20 секунд (принятый ответ на вопрос StackOverflow Изменение частоты истечения срока действия кэша ASP.NET подтверждает мое чтение этого кода с помощью Reflector). Однако для этого требуется дополнительная квалификация (для которой читается).


Asp.Net поддерживает один кэш для каждого процессора на сервере (я не уверен, что это представляют собой логические или физические процессоры); каждый из них поддерживает экземпляр CacheExpires, который имеет соответствующий Timer, который вызывает его метод FlushExpiredItems каждые двадцать секунд.

Этот метод выполняет поочередно по другому набору "ведра" данных об истечении срока хранения кеша (массив экземпляров ExpiresBucket), вызывая каждый метод ведра FlushExpiredItems.

Этот метод (ExpiresBucket.FlushExpiredItems) сначала выполняет итерацию всех элементов кэша в ковше, и если элемент истек, отметки об этом истекли. Затем (я грубо упрощаю здесь) он выполняет итерацию элементов, которые он имеет истек, и удаляет их, выполняя CacheItemRemovedCallback (на самом деле он вызывает CacheSingle.Remove, который вызывает CacheInternal.DoRemove, затем CacheSingle.UpdateCache, затем CacheEntry.Close, который фактически вызывает обратный вызов).

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

Однако при этом временном разрешении с минимальным интервалом истечения 20 секунд единственной частью процесса, который может блокироваться в течение значительного периода времени, является выполнение CacheItemRemovedCallbacks. Любой из них может, предположительно, блокировать заданный поток Timer FlushExpiredItems неопределенно. (Хотя двадцать секунд спустя, Timer будет порождать другой поток FlushExpiredItems.)

Подводя итог, Asp.Net не гарантирует, что он выполнит обратные вызовы в указанное время, но он будет делать это при некоторых условиях. Пока интервалы истечения более чем на двадцать секунд друг от друга, и пока кеш не должен выполнять трудоемкий CacheItemRemovedCallbacks (глобально - любые обратные вызовы могут помешать любым другим), он может выполнять обратные вызовы график. Это будет достаточно хорошо для некоторых приложений, но не подходит для других.

Ответ 2

Истекшие элементы не сразу удаляются из кеша, они просто помечены как истекли. Вы не получаете обратный вызов до тех пор, пока не будет пропущен кеш. Я столкнулся с этим в ASP.NET 1.1 дней, и он не изменился.

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

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