До этого момента мы рассказывали о кэшировании ваших данных. Другим типом кэширования также относящимся к веб разработке является кэширование выполняемое механизмами более высокого уровня. Это такие системы, которые кэшируют пользовательские страницы даже до того, как запрос достигнет вашего сайта.
Приведём несколько примеров:
Ваш провайдер может кэшировать определённые страницы, таким образом, если вы обращаетесь к странице сайта http://example.com/, ваш провайдер отдаст вам страницу, не выполняя запрос к сайту. Владельца сайта не будут знать об этом механизме кэширования. Провайдер находится между вами и сайтом, прозрачно выполняя все операции по кэшированию.
Ваш сайт может находится за прокси кэшем, таким как Squid (http://www.squid-cache.org/), который кэширует страницы для улучшения производительности сайта. В этом случае, каждый запрос сначала будет обработан прокси и затем, при необходимости, будет передан вашему приложению.
Ваш браузер также может кэшировать страницы. Если страница отправляет определённые заголовки, браузер будет использовать локальную копию для последующих обращений к странице без доступа к сайту даже для проверки обновления страницы.
Этот вид кэширования имеет достаточную эффективность, но несёт в себе опасность. Содержимое страниц многих сайтов различается в зависимости от того, авторизован ли посетитель или нет, а также от многих других факторов. Механизмы кэширования могут слепо сохранять страницы, основываясь на URL, которые могут содержать неверную или секретную информацию от предыдущих посетителей запрашиваемых страниц.
Например, скажем вы работаете с веб интерфейсом к электронной почте и содержимое страницы «Мой почтовый ящик» очевидно зависит от авторизованного пользователя. Если провайдер слепо закэшироует ваш сайт, то первый же посетитель этой страницы получит страницу, которая предназначалась (и была помещена в кэш) для вас. Это нехорошо.
К счастью, HTTP предоставляет решения для этой проблемы. Существует ряд HTTP заголовков, который указывает кэшам верхнего уровня, что надо изменять своё содержимое в зависимости от указанных переменных и что не следует кэшировать определённые страницы. Мы рассмотрим такие заголовки в следующих секциях.
Заголовок Vary определяет какой из заголовков запроса должен рассматриваться механизмом кэширования. Например, если содержимое страницы зависит от языковой настройки пользователя, страница укажет на это с помощью заголовка.
По умолчанию механизм кэширования Django создаёт записи в кэше, используя заданный путь (т.е., /stories/2005/jun/23/bank_robbed/). Это означает, что каждый запрос по этому URL будет использовать версию страницы из кэша, независимо от разницы между агентами пользователя (user-agent), такими как cookie или языковые настройки. Тем не менее, если эта страница генерирует различное содержание, основываясь на информации из заголовков запроса, таких как cookie или язык или другой агент пользователя, вам потребуется использовать заголовок Vary, чтобы механизм кэширования знал эту зависимость.
Для использования этого в Django следует использовать удобный декоратор для представления vary_on_headers, вот такой:
from django.views.decorators.vary import vary_on_headers
# Синтаксис для Python 2.3.
def my_view(request):
# ...
my_view = vary_on_headers(my_view, 'User-Agent')
# Синтаксис для Python 2.4+.
@vary_on_headers('User-Agent')
def my_view(request):
# ...
В данном случае механизм кэширования (такой как в Django) сохраняет отдельную версию страницы для каждого уникального агента пользователя.
Преимущество в использовании декоратора vary_on_headers вместо ручного указания заголовка Vary (как-то так response['Vary'] = 'user-agent') в том, что декоратор добавляет информацию к заголовку Vary (а он может уже существовать), а не перезаписывает уже имеющиеся в нём данные.
Вы можете передать несколько заголовков в
vary_on_headers():
@vary_on_headers('User-Agent', 'Cookie')
def my_view(request):
# ...
Это указывает кэшу верхнего уровня, что ему надо учитывать оба варианта, что означает любую комбинацию агента пользователя и cookie. Например, запрос от агента Mozilla с cookie foo=bar будет рассматриваться отдельно от запроса агента Mozilla и cookie foo=ham.
Так как обычно все используют cookie для различения запросов, нашлось место и для декоратора vary_on_cookie. Представления, приведённые ниже, эквивалентны:
@vary_on_cookie
def my_view(request):
# ...
@vary_on_headers('Cookie')
def my_view(request):
# ...
Регистр заголовков, передаваемых в
vary_on_headers(), не имеет
значения. Заголовок User-Agent эквивалентен
user-agent.
Вы также можете напрямую использовать вспомогательную функцию django.utils.cache.patch_vary_headers. Эта функция устанавливает или добавляет заголовок Vary, например:
from django.utils.cache import patch_vary_headers
def my_view(request):
# ...
response = render_to_response('template_name', context)
patch_vary_headers(response, ['Cookie'])
return response
Метод patch_vary_headers() принимает
экземпляр HttpResponse в качестве первого
аргумента и список или кортеж регистронезависимых имён
заголовков в качестве второго аргумента.
Другими проблемами при использовании кэширования являются секретность данных и вопрос хранения данных в каскадных кэшах.
Пользователь обычно сталкивается с двумя видами кэшей: кэш браузера (частный кэш) и кэш провайдера (общий кэш). Общий кэш используется рядом пользователей и находится под контролем третьего лица. Это вызывает проблему надёжности данных. Скажем, вам не захочется, чтобы номер вашего банковского счета был сохранён в общем кэше. Таким образом веб приложения должны иметь способ указать кэшу, какие данные являются частными, а какие нет.
Решением будет указание кэшу, что страница будет частной. Для того, чтобы сделать это в Django следует использовать декоратор cache_control:
from django.views.decorators.cache import cache_control
@cache_control(private=True)
def my_view(request):
# ...
Этот декоратор заботится об автоматической отправке соответствующих HTTP заголовков.
Существует несколько способов управления параметрами кэша. Например, HTTP позволяет приложения выполнять следующее:
Определять максимальное время кэширования для страницы.
Указывать должен ли кэш всегда проверять наличие новых версий и использовать сохранённые данные, только если не было изменений. (Некоторые кэши могут доставлять сохранённые данные даже в том случае, когда оригинальная страница имеет изменения, просто по той причине, что ещё не истёк срок действия закэшированной копии.)
Используйте декоратор cache_control в Django для определения этих параметров кэширования. В этом примере cache_control указывает, что требуется проверять наличие изменений в оригинальной странице при каждом доступе к ней и сохранять в кэше копии максимум 3600 секунд:
from django.views.decorators.cache import cache_control
@cache_control(must_revalidate=True, max_age=3600)
def my_view(request):
...
Любая разрешённая HTTP директива для
Cache-Control разрешена и для
cache_control(). Приведём полный список:
public=True
private=True
no_cache=True
no_transform=True
must_revalidate=True
proxy_revalidate=True
max_age=num_seconds
s_maxage=num_seconds
Совет
Для более подробной информации о HTTP директивах Cache-Control обратитесь к спецификации на http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.
Замечание
Механизм кэширования всегда устанавливает элемент
max_age заголовка кэша в соответствии со
значением из
CACHE_MIDDLEWARE_SETTINGS. Если вы
используете своё значение для max_age в
декораторе cache_control(), декоратор
будет иметь преимущество и значения заголовков будут
объединены корректно.
| Пред. | Уровень выше | След. |
| API низкого уровня | Начало | Оптимизация |
0 comments | Make a comment