#python #django #кэширование
Читал, что с помощью кеширования можно добиться значительного ускорения генерации страницы, экономя при этом ресурсы сервера. win-win, как не поверни. Достаточно ли будет навесить на view нужный декоратор, описанный в документации, чтобы все было круто?
Ответы
Ответ 1
Достаточно для полностью статических страниц. Совсем недостаточно и вредно (приводит к ошибкам, далеко не всегда очевидным) для страниц динамических. Предположим, что у нас есть некая страница, требующая кеширования. Она не статична, присутствуют элементы, наличие и вид которых зависит от конкретного пользователя и его прав. Самый простой пример - шапка сайта, где написано Привет, {{ username }}. Также есть элементы, общие для всех пользователей. Сам шаблон выглядит как-то так: {% include header.html %} {% for elem in elements %}{{ elem.text }}
{% endfor %} {% if user.has_rights %} {% endfor %} где elements = Elements.objects.filter(display=True).all(), то есть список элементов общий, но кнопка только для администраторов. Еще пример - магазин, где список товаров - общий, а корзина различна для всех. Django из коробки предоставляет несколько способов закешировать данные: Глобально для всех запросов: нужно включить UpdateCacheMiddleware и FetchFromCacheMiddleware: MIDDLEWARE_CLASSES = ( 'django.middleware.cache.UpdateCacheMiddleware', # ... Другие слои ... 'django.middleware.cache.FetchFromCacheMiddleware' ) Глобально - значит пользователь ВАСЯ залогинившись закеширует данные, специфичные для своего пользователя (например, приветствие "Привет, Вася!") и все пользователи, пришедшие после Васи получат его приветствие вместо своего. И все минуты или часы до протухания они будут видеть себя как Васю, и у них не будет никакой возможности отменить или избегать такого поведения. Это будет печальное поведение, путающее пользователей. Пригодно, если у нас пара статичных страниц и ни пользователей, ни динамического контента нет. Но тогда зачем Django? Индивидуально под каждую вьюху: @cache_page(<время в секундах>) Страдает от тех же самых проблем, но хотя бы можно поставить период обновления индивидуально. TTL (Time to live) не сделает этот инструмент волшебным, но подойдет для каких-то редких страниц без шапки с приветствием. Закешировать что-нибудь в шаблоне, используя директиву {% cache %}. Уже много лучше - можно отдельно закешировать шапку с приветствием для каждого пользователя отдельно, а для анонимов отдельно + общие данные отдельно. Однако, в этом случае страдает скорость генерации страницы, потому что процесс загрузки шаблона и его отрисовки крайне неспешный и выгоды в скорости не так высоки, как может ожидаться. Также не факт, что другие шаблонизаторы поддерживают такой функционал. Также тот факт, что мы закешировали конечный результат (HTML разметку) не отменяет необходимости обратиться к БД во вьюхе и обращаться мы тогда будем совершенно зря, потому что результаты не будут использованы. Однако, такое решение тоже имеет право существовать - генерация HTML на основе шаблонов не самая быстрая операция, а в сжатом виде занимает считанные мегабайты на тысячи страниц. Если отойти от производительности, то с точки зрения архитектуры у кеша внутри шаблонов также не все гладко. Нужно, например, внимательно помнить обо всех условиях отображения, обо всех условиях во вьюхе и в шаблоне, что в долгосрочной перспективе с несколькими разработчиками и кучей абстракций в течение лет может затруднить разработку и хуже того - чревато трудноуловимы ошибками, связанных с кешированием частей, специфичных для какой-то одной группы пользователей. Например, мы не учитываем статус суперпользвателя. Вася-админ запросил страницу первым после момента ее протухания - и вот уже в кеше страница с админскими кнопками. Или чаще наоборот - админ-Вася потеряет все свои кнопки, потому что в кеше страница для анонима. Кеширование на уровне моделей, предоставляемое несколькими сторонними приложениями. Кажется, что это и есть серебряная пуля, но на деле у такого подхода множество ограничений и самое главное ограничение - все механизмы скрыты от программиста и подключив эту штуку в уже существующий проект будет сложно ответить сломается ли что-нибудь или нет. С такими страхами невозможно будет использовать основную фичу подобного подхода (кеширование без TTL с обновлением по событиям CRUD). Если бы кеширующая библиотека предоставляла гарантии того, что как бы не изголялись, то данные в кеше никогда не протухнут - это было бы лучшее решение. Единственное решение, которое явно пишет о гарантиях (и поддерживает старую жангу 1.6+) и внушает этим доверие - django-cachalot, однако, мне неизвестно, выполняются ли это гарантии на практике в краткосрочной и долгосрочной перспективе. Даже если так, то всплывают другие ограничения - например, необходимость синхронизации часов нескольких серверов или репликаций. Забыть про все это, положившись на внутренне кеширование Django внутри QuerySet. Тоже могло бы быть каким-то временным выходом, однако, в этом случае памяти на это не напасешься.
Комментариев нет:
Отправить комментарий