Кеширование ASP.NET страниц
Понятие кеширования данных не ново. Идея хранения редко изменяемых данных с возможностью быстрого доступа к ним всегда была привлекательной. Но реализация кеширования динамических страниц оставляла желать лучшего. Dimon aka Manowar
🕛 27.10.2006, 10:56
Понятие кеширования данных не ново. Идея хранения редко изменяемых данных с возможностью быстрого доступа к ним всегда была привлекательной. Но реализация кеширования динамических страниц оставляла желать лучшего. Использование объектов Application и Session в ASP приложениях для хранения данных было затруднено из-за проблем с памятью ASP приложения при интенсивном использовании этих объектов для хранения данных, отсутствия поддержки веб-ферм и исчезании сессий.ASP.NET предоставляет простые и, вместе с тем, мощные возможности кэширования. В ASP.NET возможно кэширование страниц, частей страниц и хранение данных в глобальном объекте HttpCache.
Что же дает возможность кэширования данных? Рассмотрим следующий пример: в каталоге товаров электронного магазина категории товаров меняются очень редко (если вообще меняются). При реализации списка категорий без использования кэширования страница, выводящая их, будет обрабатываться сервером каждый раз. И при каждом вызове этой страницы будет вызываться запрос, получающий список категорий из базы данных. Намного оптимальней было бы при первом запросе этой страницы сохранить полученные данные в кеше и при последующих запросах просто выводить данные из кеша, а не делать запросы опять и опять к базе данных и не создавать эту страницу.
Кэшируемые страницы обрабатываются намного быстрее, так как они хранятся в оперативной памяти и не требуют затраты системных ресурсов на их исполнение. При этом при правильном использовании кеширования скорость работы ASP.NET приложения увеличивается в разы, а то и в десятки раз.
Рассмотрим простейший пример использования кэширования:
<%@ OutputCache Duration="60" VaryByParam="none" %> <html> <body> This page was cached at: <b> <%=DateTime.Now.ToString("G")%> </b> </body> </html>
Данный пример просто выводит текущее время сервера на страницу. Но с одним небольшим «но» - выводимая страница кешируется на сервере на 1 минуту. И при каждом последующем запросе этой страницы до тех пор, пока страница не будет удалена из кеша будет выводиться информация, сохраненная в кеше, и время на странице изменяться не будет.
Для кеширования страниц можно использовать 2 способа:
Использование директивы OutputCache
Использование класса HttpCachePolicy.
Оба способа одинаковы по своим действиям, но использование директивы OutputCache является более интуитивно понятным.
Использование директивы OutputCache
Приведенный выше пример демонстрирует как использовать директиву OutputCahce для быстрой активизации кеширования ASP.NET страниц. Данный пример очень прост - в нем используется единственный параметр для указания времени хранения кешированной информации и указано, что данная страница будет иметь только одну кешированную версию независимо от тех или иных параметров.
Общий формат директивы OutputCache следующий:
<%#@ OutputCache Duration="value" Location="value" VaryByParam="value" VaryByHeader="value" VaryByCustom="value" %>
Теперь рассмотрим более подробно директиву OutputCache и ее атрибуты и то, как они влияют на кеширование ASP.NET страниц.
Атрибут Duration
Атрибут Duration указывает промежуток времени в секундах в течение которого страница будет храниться в кеше. В приведенном выше примере страница будет храниться в кеше 60 секунд. Если в это время будет послан запрос этой страницы - она не будет выполнена опять на сервере, а будет возвращена из кеша.
Атрибут Duration обязателен. Если он будет опущен - ASP.NET сгенерит исключение.
Атрибут Location
Атрибут Location указывает на то, где будут храниться кешированные страницы. С помощью этого атрибута можно указывать на то, что страница будет кешироваться в памяти сервера или в клиентском браузере. Этот атрибут может принимать следующие значения:
Any - Указывает на то, что страница будет кешироваться везде, где только возможно: на сервера, в клиентском браузере и на отправляющем сервере. По умолчанию атрибут Location имеет значение Any
Client - Страница будет кешироваться только в клиентском браузере (если браузер разрешает кеширование страниц)
Downstream - Страница будет кешироваться на отправляющем сервере
None - Кеширование запрещено
Server - Страница кешируется на сервере, обрабатывающем запрос
Немного изменим предыдущий пример для иллюстрации применения атрибута Location:
<%@ OutputCache Duration="60" VaryByParam="none" Location=”Server” %> <html> <body> This page was cached at: <b> <%=DateTime.Now.ToString("G")%> </b> </body> </html>
Теперь страница будет кешироваться только на сервере. Рекомендую попробовать использовать различные значения атрибута Location и сравнить результаты.
Атрибут VaryByParam
ASP.NET позволяет иметь несколько представлений одной и той же страницы в кеше. Страница может кешироваться по разному в зависимости от различных параметров - передаваемых параметров формы и строки запроса, HTTP заголовков и определяемых параметров. Атрибут VaryByParam управляет кешированием страницы в зависимости от передаваемых ей параметров формы и строки запроса. В предыдущем примере значение VaryByParam было установлено в none. Установка этого параметра в none означает, что страница будет иметь одно и то же представление независимо от передаваемых ей параметров. Однако зачастую веб страницы строятся динамически в зависимости от передаваемых им параметров. Например страницу, отображающая список товаров определенной категории, можно кешировать в зависимости от ID категории, передаваемого этой странице в качестве параметра.
Вернемся к рассмотренному нами ранее примеру веб форума. Конкретней к странице отображения сообщения. Теоретически текст сообщения в форуме меняется крайне редко, если вообще меняется (ну разве что администратор форума решил позаниматься немного цензурой). И страница, выводящая сообщение из форума, является хорошим кандидатом на кеширование.
Все, что необходимо сделать для того, чтобы активизировать кеширование для этой страницы, это добавить следующую директиву в начале файла:
<%@ OutputCache Duration="3600" VaryByParam=”uid” %>
Данный формат директивы OutputCache активизирует кеширование страницы вывода сообщений форума в зависимости от uid сообщения. И теперь в кеше будет храниться уже не одна версия message.aspx, а, максимум, столько же версий, сколько сообщений в форуме. И если несколько пользователей захотят просмотреть одно и то же сообщение в течении часа - страница будет выполнена только один раз для первого пользователя. Остальные получат представление этой страницы из кеша.
Значением параматра VaryByParam может быть не только одно имя параметра. Вы можете указывать параметры через точку с запятой, например так:
<%@ OutputCache Duration="300" VaryByParam=”forum_id;uid” %>
Или возможно использвать специальное значение этого атрибута - симовл «*». Использование символа «*» в качестве значения атрибута VaryByParam указывает на то, что страница будет кешироваться в зависимости от значений всех передаваемых ей параметров.
Атрибут VaryByHeader
С помощью этого параметра можно управлять кешированием страницы в зависимости от различных значений HTTP заголовков. Значениями этого параметра можно использовать следующие названия HTTP заголовков:
Accept
Accept-Charset
Accept-Encoding
Accept-Language
Authorization
Content-Encoding
Expect
From
Host
If-Match
If-Modified-Since
If-None-Match
If-Range
If-Unmodified-Since
Max-Forwards
Proxy-Authorization
Range
Referer
TE
User-Agent
Вы можете определять несколько названий HTTP заголовков, разделенных точкой с запятой, как значение атрибута VaryByHeader
<%@ OutputCache Duration=”60” VaryByHeader=”Referer;Content-Encoding” %>
В приведенном выше примере страница будет кешироваться в зависимости от значений HTTP заголовков Referer и Content-Encoding. То есть новое представление страницы будет сохраняться в кеше для каждой уникальной пары значений заголовков Referer и Content-Encoding.
Атрибут VaryByCustom
Использование атрибута VaryByCustom позволяет управлять кешированием ASP.NET страниц в зависимости от параметров, определенных разработчиком. По умолчанию данный атрибут принимает своим значением только значение “Browser”. Если использовать этот атрибут с значением “Browse”, страница будет кешироваться в зависимости от типа клиентского браузера и старшего номера версии.
<%@ OutputCache Duration=”60” VaryByCustom=”Browser” %>
Разработчики могут создавать свои значения для атрибута VaryByCustom с помощью переопределения метода HttpApplication.GetVaryByCustomString. Данный метод переопределяется в файле global.asax.
Использование объекта HttpCachePolicy
Ранее уже упоминалось что управлять кешированием ASP.NET страниц можно двумя способами - с помощью директивы OutputCache и с помощью класса HttpCachePolicy. Если более подробно раскрыть эти пути, то выяснится, что директива OutoutCache просто представляет интуитивно понятный интерфейс для класса HttpCachePolicy. При этом, естественно, накладывая некоторые свои ограничения. Например используя директиву OutputCache нельзя установить абсолютное время окончания срока хранения объекта в кеше. Использование класса HttpCachePolicy представляет такую возможность.
Доступ к экземпляру класса HttpCachePolicy можно получить с помощью свойства Cache объекта Response.
Рассмотрим пример использования HttpCachePolicy для кеширования страницы.
<script language=”c#” runat-“server”> void PageLoad(object sender, EventArgs e) { Response.Cache.SetExpires(DateTime.Now.AddMinutes(2); Response.Cache.SetCacheability(HttpCacheability.Public); } </script> <html> <body> This page was cached at: <b> <%=DateTime.Now.ToString("G")%> </b> </body> </html>
В приведенном выше примере кеширование активизируется вызовом методов SetExpires и SetCacheability в обработчике события Load для веб формы. В данном конкретном случае страница кешируется на 2 минуты и сохраняется везде, где может сохраниться (аналогично использованию атрибута Location=”Any”).
Не имеет смысла приводить здесь полностью описание класса HttpCachePolicy - те, кому это интересно, могут найти описание данного класса в документации .NET Framework. Здесь же я приведу только наиболее интересные методы данного класса.
Как уже указывалось ранее, метод SetExpires позволяет установить абсолютное время, после которого страница будет удалена из кеша. Следующий пример устанавливает время окончания пребывания страницы в кеше на 18:00 локального времени:
Response.Cache.SetExpires(DateTime.Parse("18:00"));
Можно установить скользящее время удаления страницы из кеша. Данное свойство кеширования активизируется с помощью вызова метода SetSlidingExpiration с параметром true. При этом время хранения страницы в кеше будет автоматически обновляться после каждого запроса.
Заключение
Использование возможностей кеширования, представляемых ASP.NET, позволит увеличить скорость работы веб приложений в разы. Но к вопросу кеширования нужно подходить разумно, иначе можно добиться просто таки непредсказуемых результатов - от неверного отображения данных до быстрого заполнения памяти сервера.