All streams
Search
Write a publication
Pull to refresh
386
0
Дмитрий Котеров @DmitryKoterov

Пользователь

Send message
В статье есть предложение поэкспериментировать. Возможно, если указать более жесткий Cache-Control, то не потребуется удалять Last-Modified.

Нужно только учитывать, что PHP выставляет Last-Modified при вызова session_start(). Причем выставляет он его равным… дате изменения файла PHP, который запустился в результате запроса. В большинстве случаев это какой-нибудь index.php из FrontController, который вообще не меняется. Соответственно, те, кто использует сессии, чаще всего имеют неправильный Last-Modified.
Примерно вот так:

location ~ ^(здесь_урлы_которые_нужно_кэшировать)$ {
    set $test_cache_on "$cookie_debugMode|$arg_nocache|любые_другие_значения_непустые_для_отключения_кэша";
    if ($test_cache_on = "") {
        rewrite .* /php_cache last;
    }
    rewrite ^ /php_no_cache last;
}

location /php_cache {
    internal;
    ...
    fastcgi_cache wholepage;
    ...
}

Я допишу в статье попозже.
ОК, значит, у нас есть альтернативное мнение. Может, потом как-нибудь появится и альтернативная статья… это всегда интересно.
Вы так уверенно говорите… Хочу спросить, была ли у Вас практика в этом вопросе именно применительно к nginx?
По пункту 1 — там, кажется, решение тоже нетривиальное. Допишу скоро.
По пункту 2 — лучше не делайте так, используйте sysoev.ru/nginx/docs/http/ngx_http_memcached_module.html — он гораздо удобнее, если речь заходит об очистке кэша из приложения.
Да, кстати, я применял такую технику выключения кэша для залогина. Надо будет дописать это в статье.
Эта директива блокирует выдачу в браузер ЛЮБЫХ команд установки кук. Но, заметьте, только УСТАНОВКИ. Сами куки, уже установленные где-то в другой части сайта, никуда не денутся (потому что они управляются браузером, сервер их не ставит, а только читает).

Да, в кэш-файле куки все останутся. Туда вообще попадет ровно то, что выдал PHP, без изменений (и, кажется, на это нельзя повлиять). Можно вырезать только при отдаче.
Бэкендов же много. Не обязательно на один все запросы пойдут, они распределятся по кластеру.
Важно, чтобы Last-Modified менялся каждую секунду, т.е. реально содержал текущее время. Иначе сервер будет отдавать Not Modified при рефреше страницы, что в случае ротации не очень хорошо. Впрочем, можно поэкспериментировать с Cache-Control: no-cache, no-store, must-revalidate. Возможно, тогда с Last-Modified и не понадобятся манипуляции, я пока не проверял во всех браузерах, как они реагируют.
Когда в приложении огромное количество стратегий для полностраничного кэширования, ИМХО стоит подумать, а нельзя ли их все свести к одному-двум. На моей практике именно так происходило: в одном проекте было вообще всего одно правило для всех страниц (все страницы для Гостя кэшировались), в другом — два правила (одно для склеенных CSS+JS, другое — для группы страниц с высокой нагрузкой). Полностраничное кэширование — это не кэширование блоков/выборок из БД, оно обычно сильно проще и гораздо менее универсально.
Не столько PHP уродлив, сколько программисты непредсказуемы. Карандаш на острие стьит, но недолго; лучше его перевернуть и поставить устойчиво. Отсюда и совет.
Да, кстати, хочу подчеркнуть, что полностраничное nginx-кэширование — это не панацея, это просто один из инструментов, который иногда очень хорошо подходит. Большинство кэширования в реальных приложениях, наверное, располагается между слоем модели и слоем доступа к БД. Но это совсем-совсем другое. Здесь же речь идет только о полностраничном кэшировании.
> ведь страницы кешируются безусловно, без учета мнения приложения, в обход его логики
Это не совсем так. В nginx неплохие возможности по анализу параметров, кук и т.д.

> Правильнее, наверно, все же, в приложении отдавать правильные http-заголовки, а nginx пусть их интерпретирует :)
Так далеко не всегда получается, в статье частично обосновывается, почему. Штука в том, что до приложения дело не доходит при кэш-попадании. Соответственно, никто, кроме nginx, и не может решить, валиден кэш или нет.
Кроме того, все активные ключи и информация о данных хранятся в разделяемой памяти — зоне, имя и размер которой задаётся параметром keys_zone. Если к данным кэша не обращются в течение времени, заданного параметром inactive, то данные удаляются, независимо от их свежести. По умолчанию inactive равен 10 минутам.
Это именно время хранения, а не время валидности. Цитата из документации:

Это мегабайты, размер shared memory для еще более быстрого доступа к кэшу. Документация рулит.
Кэш PHP на уровне ob_start() — это, конечно, лучше, чем отсутствие полностраничного кэша. Однако все равно потери будут порядка 5-10 мс на вызов, в то время как в случае nginx они практически нулевые.

Что касается
> Как бы вы посоветовали сделать так, чтобы ключ кеширования можно было бы устанавливать в самом PHP?
то использовать кэш nginx в таком режиме не получится: ведь чтобы определить ключ, вам потребуется запустить PHP-скрипт, а это уже промах мимо кэша по определению. Вся суть nginx-кэширования в том, чтобы не допускать ряд запросов вообще до PHP.

Я рекомендую всю логику кэширования прописывать в едином месте: либо в конфиге nginx (и хранить его в системе контроля версий, конечно же), либо — в PHP (но тогда nginx-кэширование не используется). А чтобы для разных групп юзеров кэши были разные, установите текущую группу в куку $group, а потом замешайте $cookie_group (переменная такая в nginx создается для этой куки) в ключ кэширования. Это один из вариантов.
Firefox. А при чем тут браузер? Это прямо выдача в HTML такая. Видимо, забыли шаблон наложить на XML, либо что-то подобное…
Сорри, добавил. Тут в хабраредакторе сломался предпросмотр: жуть как неудобно статью форматировать. Вместо превью выдается что-то типа <redirect_url>http://habrahabr.ru/blogs/hi/72539/</redirect_urlok. Вот и приходится «на живом» править.

Information

Rating
Does not participate
Location
Россия
Registered
Activity