Comments 83
хабракат...(
-4
Сорри, добавил. Тут в хабраредакторе сломался предпросмотр: жуть как неудобно статью форматировать. Вместо превью выдается что-то типа <redirect_url>http://habrahabr.ru/blogs/hi/72539/</redirect_urlok. Вот и приходится «на живом» править.
+2
Что делать со страницами, которые полностью динамические? Как принудительно отключить для них кеширование и нужно ли это делать?
Как бы вы посоветовали сделать так, чтобы ключ кеширования можно было бы устанавливать в самом PHP? К примеру, кешировать страницу в зависимости от группы пользователей?
Как бы вы посоветовали сделать так, чтобы ключ кеширования можно было бы устанавливать в самом PHP? К примеру, кешировать страницу в зависимости от группы пользователей?
0
Мне кажется что тут уже дело даже не в жинксе, можно средствами пхп делать тот же кеш и им управлять, добавился комент — переписали кеш если это возможно, инструментов очень много и все зависит от типа сайта. И не бойтесь пользоваться кешированием через пхп, я понимаю что это ресурсозатратно, но доступ к базе и отдача осуществляется намного дольше. А харды у нас сегодня дешевле процов. Если же сайт «очень динамичен» и очень много пользователей а решение нужно с серверной стороны, то думаю что поставив кеш даже на 30 секунд будет видно спад нагрузки. В основном время от прочтения топика и коментирования проходит не меньше.
-1
Кэш PHP на уровне ob_start() — это, конечно, лучше, чем отсутствие полностраничного кэша. Однако все равно потери будут порядка 5-10 мс на вызов, в то время как в случае nginx они практически нулевые.
Что касается
> Как бы вы посоветовали сделать так, чтобы ключ кеширования можно было бы устанавливать в самом PHP?
то использовать кэш nginx в таком режиме не получится: ведь чтобы определить ключ, вам потребуется запустить PHP-скрипт, а это уже промах мимо кэша по определению. Вся суть nginx-кэширования в том, чтобы не допускать ряд запросов вообще до PHP.
Я рекомендую всю логику кэширования прописывать в едином месте: либо в конфиге nginx (и хранить его в системе контроля версий, конечно же), либо — в PHP (но тогда nginx-кэширование не используется). А чтобы для разных групп юзеров кэши были разные, установите текущую группу в куку $group, а потом замешайте $cookie_group (переменная такая в nginx создается для этой куки) в ключ кэширования. Это один из вариантов.
Что касается
> Как бы вы посоветовали сделать так, чтобы ключ кеширования можно было бы устанавливать в самом PHP?
то использовать кэш nginx в таком режиме не получится: ведь чтобы определить ключ, вам потребуется запустить PHP-скрипт, а это уже промах мимо кэша по определению. Вся суть nginx-кэширования в том, чтобы не допускать ряд запросов вообще до PHP.
Я рекомендую всю логику кэширования прописывать в едином месте: либо в конфиге nginx (и хранить его в системе контроля версий, конечно же), либо — в PHP (но тогда nginx-кэширование не используется). А чтобы для разных групп юзеров кэши были разные, установите текущую группу в куку $group, а потом замешайте $cookie_group (переменная такая в nginx создается для этой куки) в ключ кэширования. Это один из вариантов.
+2
Имелись ввиду страницы, содержимое которых генерируется в зависимости от того, какой пользователь залогинен.
0
Респект Диме за статью, ее прочитал еще в рассылке на Алехе.
я тут сейчас модуль с маемкешом заканчиваю…
вот только не надо, что изобретаю велосипед… модуль нужен для записи в мемкеш (типа REST).
так вот, о чем я…
он в 80 раз быстрее работает, чем то-же самое ранее делали через пхп.
я тут сейчас модуль с маемкешом заканчиваю…
вот только не надо, что изобретаю велосипед… модуль нужен для записи в мемкеш (типа REST).
так вот, о чем я…
он в 80 раз быстрее работает, чем то-же самое ранее делали через пхп.
0
Я чего-то не пойму,
0
keys_zone=wholepage:50m;
Тут задается время кеширования (50m)?
0
Это мегабайты, размер shared memory для еще более быстрого доступа к кэшу. Документация рулит.
+3
Время хранения задается в той же строчке примерно так:
fastcgi_cache_path /tmp/nginx/ levels=1:2 keys_zone=fastcgi_cache:16m max_size=256m inactive=1d;
0
Это именно время хранения, а не время валидности. Цитата из документации:
0
Кроме того, все активные ключи и информация о данных хранятся в разделяемой памяти — зоне, имя и размер которой задаётся параметром keys_zone. Если к данным кэша не обращются в течение времени, заданного параметром inactive, то данные удаляются, независимо от их свежести. По умолчанию inactive равен 10 минутам.
0
Мда, кеширование на уровне nginx конечно очень призводительно, но по моему, так это как-то криво, ведь страницы кешируются безусловно, без учета мнения приложения, в обход его логики. И вообще, как-то коряво имхо.
Правильнее, наверно, все же, в приложении отдавать правильные http-заголовки, а nginx пусть их интерпретирует :)
Правильнее, наверно, все же, в приложении отдавать правильные http-заголовки, а nginx пусть их интерпретирует :)
0
> ведь страницы кешируются безусловно, без учета мнения приложения, в обход его логики
Это не совсем так. В nginx неплохие возможности по анализу параметров, кук и т.д.
> Правильнее, наверно, все же, в приложении отдавать правильные http-заголовки, а nginx пусть их интерпретирует :)
Так далеко не всегда получается, в статье частично обосновывается, почему. Штука в том, что до приложения дело не доходит при кэш-попадании. Соответственно, никто, кроме nginx, и не может решить, валиден кэш или нет.
Это не совсем так. В nginx неплохие возможности по анализу параметров, кук и т.д.
> Правильнее, наверно, все же, в приложении отдавать правильные http-заголовки, а nginx пусть их интерпретирует :)
Так далеко не всегда получается, в статье частично обосновывается, почему. Штука в том, что до приложения дело не доходит при кэш-попадании. Соответственно, никто, кроме nginx, и не может решить, валиден кэш или нет.
0
Да, кстати, хочу подчеркнуть, что полностраничное nginx-кэширование — это не панацея, это просто один из инструментов, который иногда очень хорошо подходит. Большинство кэширования в реальных приложениях, наверное, располагается между слоем модели и слоем доступа к БД. Но это совсем-совсем другое. Здесь же речь идет только о полностраничном кэшировании.
0
UFO just landed and posted this here
Не столько PHP уродлив, сколько программисты непредсказуемы. Карандаш на острие стьит, но недолго; лучше его перевернуть и поставить устойчиво. Отсюда и совет.
0
UFO just landed and posted this here
Вы так уверенно говорите… Хочу спросить, была ли у Вас практика в этом вопросе именно применительно к nginx?
0
если бы по невнимательности программиста все вылилось действительно лишь в незакешированную страницу — то да.
0
Допустим для главной страницы мы настроили кеширование. И логика «описывать правила кеширования в одном месте» призывает нас настроить кеширование и для всех прочих страниц. А как быть в случае когда этих страниц очень много и требуются очень отличающиеся правила.
Можно разделить условно страницы, которые очень часто обновляются и очень редко, а также существует некая золотая середина.
Соответственно получается такая картина:
Вариант1: Мы оптимизируем выдачу часто-обновляемых страниц. При этом получаем дополнительную нагрузку на редко-обновляемые страницы (то есть они будут дергаться в любом случае раз в секунду, так как PHP уже не может сказать, что страница не менялась, так?).
Вариант2: противоположный случай (просто для контрпримера) когда мы оптимизируем выдачу редко-обновляемых и получаем неактуальную информацию.
Я так понимаю, что логичным выходом из этого будет индивидуальный подход к разным разделам и даже конкретным страницам. Но не создаст ли это еще большие сложности с тем, что надо будет индивидуально затачивать кеш огромного числа страниц (а потом добавится какой-нибудь баннер и придется снова менять логику кеширования), а конфиг nginx разрастется до безумных пределов (и соответственно сложность управления им сильно возрастет)?
Можно разделить условно страницы, которые очень часто обновляются и очень редко, а также существует некая золотая середина.
Соответственно получается такая картина:
Вариант1: Мы оптимизируем выдачу часто-обновляемых страниц. При этом получаем дополнительную нагрузку на редко-обновляемые страницы (то есть они будут дергаться в любом случае раз в секунду, так как PHP уже не может сказать, что страница не менялась, так?).
Вариант2: противоположный случай (просто для контрпримера) когда мы оптимизируем выдачу редко-обновляемых и получаем неактуальную информацию.
Я так понимаю, что логичным выходом из этого будет индивидуальный подход к разным разделам и даже конкретным страницам. Но не создаст ли это еще большие сложности с тем, что надо будет индивидуально затачивать кеш огромного числа страниц (а потом добавится какой-нибудь баннер и придется снова менять логику кеширования), а конфиг nginx разрастется до безумных пределов (и соответственно сложность управления им сильно возрастет)?
0
написание конфигов можно автоматизировать :)
0
Когда в приложении огромное количество стратегий для полностраничного кэширования, ИМХО стоит подумать, а нельзя ли их все свести к одному-двум. На моей практике именно так происходило: в одном проекте было вообще всего одно правило для всех страниц (все страницы для Гостя кэшировались), в другом — два правила (одно для склеенных CSS+JS, другое — для группы страниц с высокой нагрузкой). Полностраничное кэширование — это не кэширование блоков/выборок из БД, оно обычно сильно проще и гораздо менее универсально.
0
Кеширование для гостя это интересно… Это не на webo.in случаем? :-)
В любом случае большое спасибо за интересный материал, будем проверять на практике.
В любом случае большое спасибо за интересный материал, будем проверять на практике.
0
конфиг и так разрастается до безумных пределов
банеры отдаются яваскриптом
а вот подход к кешированию действительно нужен комплекксный: где надо логику отдаем энджиниксу,
а где нужно -приложению. Где нужно кешируем блок и собираем через SSI
а где надо — через шаблонизатор.
банеры отдаются яваскриптом
а вот подход к кешированию действительно нужен комплекксный: где надо логику отдаем энджиниксу,
а где нужно -приложению. Где нужно кешируем блок и собираем через SSI
а где надо — через шаблонизатор.
0
Отличная статься, огромное спасибо.
Можно задавать Last-Modified явно в конфиге и обновлять по крону раз в сутки или реже/чаще.
Конфиг с этой директивой можно инклюдить, для простоты.
Можно задавать Last-Modified явно в конфиге и обновлять по крону раз в сутки или реже/чаще.
Конфиг с этой директивой можно инклюдить, для простоты.
0
Важно, чтобы Last-Modified менялся каждую секунду, т.е. реально содержал текущее время. Иначе сервер будет отдавать Not Modified при рефреше страницы, что в случае ротации не очень хорошо. Впрочем, можно поэкспериментировать с Cache-Control: no-cache, no-store, must-revalidate. Возможно, тогда с Last-Modified и не понадобятся манипуляции, я пока не проверял во всех браузерах, как они реагируют.
0
Планируется ли еще что-нибудь вкусное про nginx выложить?)
0
да, статья хорошая. Но все же хорошо было бы озвучить общий подход к серверному кэшированию. Если это — только один из инструментов, то каковы критерии применения остальных? Когда мы можем перекинуть расчет валидности кэша на фронтенд, когда — на бэкенд, а когда — вообще не кэшировать, либо кэшировать отдельные блоки.
Да, по поводу4 блоков по 200мс — это сильно :) Особенно, если число ядер у бэкенда меньше, чем 4 — потоки будут изумительно параллелиться :)
Да, по поводу4 блоков по 200мс — это сильно :) Особенно, если число ядер у бэкенда меньше, чем 4 — потоки будут изумительно параллелиться :)
0
Спасибо!
0
отличная статья
0
Правильно ли я понял первую часть статьи в этом месте:
# Гарантируем, что разные пользователи не получат одну и ту же сессионную Cookie.
fastcgi_hide_header «Set-Cookie»;
Сценарий — заходит Пользователь1, кеш пустой, запрос обрабатывается php, который ставит куку с идентификатором сессии, nginx кладет ответ в кеш и прячет куку.
Заходит Пользователь2. Если я правильно понял, он получит данные из кеша, но при этом не получит куки с идентификатором сессии?
# Гарантируем, что разные пользователи не получат одну и ту же сессионную Cookie.
fastcgi_hide_header «Set-Cookie»;
Сценарий — заходит Пользователь1, кеш пустой, запрос обрабатывается php, который ставит куку с идентификатором сессии, nginx кладет ответ в кеш и прячет куку.
Заходит Пользователь2. Если я правильно понял, он получит данные из кеша, но при этом не получит куки с идентификатором сессии?
0
практически правильно, только один нюанс — в закешированной странице кука останется, а прячется она при отдаче ответа.
а для индентификатора сессии всегда можно использовать встроенное средство nginx — модуль userid
а для индентификатора сессии всегда можно использовать встроенное средство nginx — модуль userid
0
все таки не очень понятно, а если у меня допустим не session id в куке а какие то полезные данные приложения (допустим, настройки языка)?
1. сохранятся ли они в кеш?
2. каким образом они будут обработаны для второго пользователя?
1. сохранятся ли они в кеш?
2. каким образом они будут обработаны для второго пользователя?
0
Эта директива блокирует выдачу в браузер ЛЮБЫХ команд установки кук. Но, заметьте, только УСТАНОВКИ. Сами куки, уже установленные где-то в другой части сайта, никуда не денутся (потому что они управляются браузером, сервер их не ставит, а только читает).
Да, в кэш-файле куки все останутся. Туда вообще попадет ровно то, что выдал PHP, без изменений (и, кажется, на это нельзя повлиять). Можно вырезать только при отдаче.
Да, в кэш-файле куки все останутся. Туда вообще попадет ровно то, что выдал PHP, без изменений (и, кажется, на это нельзя повлиять). Можно вырезать только при отдаче.
0
nginx пишет в файл кеша весь документ, который получает, включая заголовки (т.е. все куки, которые вы передаете клиенту сохранятся). Что с ними делать дальше — это уж как вам нравится — прячьте куки, оставляйте. Только один кукис спрятать, а другой показать не получится (использование модуля sub для этих целей рассматривать не будем:) ).
Если вы прячете куки — то они не будут отданы и первому пользователю.
Если вы прячете куки — то они не будут отданы и первому пользователю.
0
Дмитрий можно вопрос?
У меня главная — индивидуальна для каждого зареганого пользователя и статична для всех анонимов.
Т.е. посетитель N1 видит одно, а посетитель 2 — совсем другое.
Второй нюанс, для пользователей заведены псевдосубдомены. Насколько я понял nginx «их не видит», и когда пользователь заходит, например на страницу recoilme.mp3tter.com/ nginx послает его на индексную страницу, в которой уже определяется принадлежность соответствующему субдомену.
Третье — пользователь загрузил файл (оставил сообщение), при обновлении надо отразить с последними изменениями главную…
Кругом жопа…
Я отчаялся реализовать кэш в данных условиях. Просто насколько я понял Вы тоже боролись с твиттер-лайк сайтом, может быть подскажете реализуемо ли это в принципе нгинксом? Или на уровне приложения реализовывали? В каком примерно направлении копать?
Заранее спасибо.
У меня главная — индивидуальна для каждого зареганого пользователя и статична для всех анонимов.
Т.е. посетитель N1 видит одно, а посетитель 2 — совсем другое.
Второй нюанс, для пользователей заведены псевдосубдомены. Насколько я понял nginx «их не видит», и когда пользователь заходит, например на страницу recoilme.mp3tter.com/ nginx послает его на индексную страницу, в которой уже определяется принадлежность соответствующему субдомену.
Третье — пользователь загрузил файл (оставил сообщение), при обновлении надо отразить с последними изменениями главную…
Кругом жопа…
Я отчаялся реализовать кэш в данных условиях. Просто насколько я понял Вы тоже боролись с твиттер-лайк сайтом, может быть подскажете реализуемо ли это в принципе нгинксом? Или на уровне приложения реализовывали? В каком примерно направлении копать?
Заранее спасибо.
0
В таком сайте лучше всего хранить главную страницу в memcache и отдавать ее отуда. Если изменяется — просто перерисовываем в памяти.
0
Не выйдет мне кажется. Главная для всех разная. Более того, recoilme.mp3tter.com для рекойлми != recoilme.mp3tter.com для другого посетителя.
Я в отчаянии. Единственное что наверно можно придумать тут — кешировать запросы. Но и тут жопа. Сиквуль заточен для операций над пулом записей, а для кеша эфективней порезать запросы по одной записи и потом собирать результаты в массив. Как это разрулил twitter — вообще непонятно…
Либо я чего то недопонимаю…
Я в отчаянии. Единственное что наверно можно придумать тут — кешировать запросы. Но и тут жопа. Сиквуль заточен для операций над пулом записей, а для кеша эфективней порезать запросы по одной записи и потом собирать результаты в массив. Как это разрулил twitter — вообще непонятно…
Либо я чего то недопонимаю…
0
у меня появилась такая идея — кладем данные для хозяина поддомена в мемкеш с ключем, скажем ид его сессии + хост, при заходе на страницу пользователями проверяем, наличие такого ключа, если нет — идем в именованный локейшн из которого проверяем наличие ключа «гость + хост», если нет — лезем в еще один именованный локейшн, который лезет в пхп. Единственное — я не помню, можно ли переопределять error_page внутри именованного локейшена.
слегка сумбурно, но может чем поможет :)
слегка сумбурно, но может чем поможет :)
0
Почему невыйдет?
Для анонимных она одинаковая, верно?
А для зарегенных можно подготавливать статику на диск и отдавать ее напрямую
Для анонимных она одинаковая, верно?
А для зарегенных можно подготавливать статику на диск и отдавать ее напрямую
0
По первому пункту — нгинкс можно научить смотреть есть ли сессия (допустим, что у неавторизованных её нет) и если да, то передавать управление пхп, если нет — отдать кеш.
0
Если у вас контент страницы зависит от некоего user_id, то засуньте тогда значение этого user_id в fastcgi_cache_key — тогда будут кешироваться разные варианты страницы в зависимости от cache_key.
0
Спасибо за статью, как раз подумываю переложить кеширование с Catalyst::Plugin::PageCache на nginx, руки не доходили проверить, будет ли кешироваться страница с обработанными SSI-директивами, или без изменений. Было бы замечательно, если:
1. Можно было бы кешировать страницу только для неавторизованных пользователей. Описанный в документации способ
2. Была бы возможность принудительно очищать закешированную страницу по запросу из приложения. Надо проверить, будет ли работать просто удаление файла с именем, равным md5 от
1. Можно было бы кешировать страницу только для неавторизованных пользователей. Описанный в документации способ
fastcgi_cache_key "...$cookie_user";
, не подходит — нужно кешировать только в случае пустой куки, а не для каждого её значения. Хотя, можно попробовать загнать директиву fastcgi_cache
в if.2. Была бы возможность принудительно очищать закешированную страницу по запросу из приложения. Надо проверить, будет ли работать просто удаление файла с именем, равным md5 от
fastcgi_cache_key
. 0
По пункту 1 — там, кажется, решение тоже нетривиальное. Допишу скоро.
По пункту 2 — лучше не делайте так, используйте sysoev.ru/nginx/docs/http/ngx_http_memcached_module.html — он гораздо удобнее, если речь заходит об очистке кэша из приложения.
По пункту 2 — лучше не делайте так, используйте sysoev.ru/nginx/docs/http/ngx_http_memcached_module.html — он гораздо удобнее, если речь заходит об очистке кэша из приложения.
+1
Эх, тогда, видимо, придется оставить использование Catalyst::Plugin::PageCache — абсолютно прозрачно для приложения и можно быстро сменить кеширующий бэкенд с файлов на тот же мемкеш или memory-mapped файлы. Слишком уж негибкое получается кеширование nginx'ом, хоть, наверное, и быстрей на порядок, но мне пока и кеша на уровне приложения хватает.
0
Хотелось-бы увидеть пример отключения кэша при наличие определённой куки (отключение кэша для зарегеных) (реализация сейчас заставляет юзать X-Accel-Expires в приложении)
+2
Примерно вот так:
Я допишу в статье попозже.
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; ... }
Я допишу в статье попозже.
+1
Чертовски хочется
if($cookie_userid) fastcgi_cache off;
:)
if($cookie_userid) fastcgi_cache off;
:)
+1
set $tocache 1;
if ($http_cookie ~* "sessionId=([^;]+)(?:;|$)") {
set $tocache 0;
}
...
if ($tocache) {
fastcgi_pass ...
}
примерно так
0
наверное, вместо set $tocache 0 можно поставить и fastcgi_cache off, хотя я не гуру настроек нгинкса.
0
А в чём смысл этой конструкции? fastcgi_pass для всех должен быть один.
0
Я приводил мой вариант несколько дней назад
0
А при кэшировании nginx+memcache есть какой-нибудь аналог директиве fastcgi_hide_header «Set-Cookie»?
0
а как быть с SE оптимищацией и Last-Modified? гугл насколько мне известно смотрит на этот заголовок.
0
В статье есть предложение поэкспериментировать. Возможно, если указать более жесткий Cache-Control, то не потребуется удалять Last-Modified.
Нужно только учитывать, что PHP выставляет Last-Modified при вызова session_start(). Причем выставляет он его равным… дате изменения файла PHP, который запустился в результате запроса. В большинстве случаев это какой-нибудь index.php из FrontController, который вообще не меняется. Соответственно, те, кто использует сессии, чаще всего имеют неправильный Last-Modified.
Нужно только учитывать, что PHP выставляет Last-Modified при вызова session_start(). Причем выставляет он его равным… дате изменения файла PHP, который запустился в результате запроса. В большинстве случаев это какой-нибудь index.php из FrontController, который вообще не меняется. Соответственно, те, кто использует сессии, чаще всего имеют неправильный Last-Modified.
0
Судя по всему, приведенные примеры настроек примерно наполовину представляет из себя летопись хождения по граблям — как говорит сам автор, «каждая строчка писана кровью».
Сначала программист, не подозревающий о Cache-Control, наступает на первые грабли и случайно отключает кеширование главной страницы. Автор предполагает, что лучшее решение это запрет Cache-Control на корню, но в результате наступает на несколько очередных грабель — во-первых, из-за отсутствия Cache-Control начинают кешироваться Cookie, а во-вторых, из-за отрезанных Expires страницы начинают плохо кешироваться в броузерах, которые в результате шлют слишком много запросов с If-Modified-Since. С первым справляемся отрезанием самих Cookie, а со вторым — кешированием ответов 304 Not Modified. Напоследок же автор пытается эмулировать Cache-Control через отрезание Last-Modified, что уже напрямую идет вразрез RFC на HTTP/1.1 и скорее всего, чревато очередными граблями.
В итоге же все это комсомольское путешествие оказывается всего-лишь следствием одного из возможных решений специфической проблемы автора и совсем не обязательно разламывать управление кешированием HTTP из-за того, что какой-то программист однажды накосячил. Так что рекомендую воспринимать эту статью с хорошей долей grain of salt и думать самостоятельно о последствиях отключения чего-либо.
Сначала программист, не подозревающий о Cache-Control, наступает на первые грабли и случайно отключает кеширование главной страницы. Автор предполагает, что лучшее решение это запрет Cache-Control на корню, но в результате наступает на несколько очередных грабель — во-первых, из-за отсутствия Cache-Control начинают кешироваться Cookie, а во-вторых, из-за отрезанных Expires страницы начинают плохо кешироваться в броузерах, которые в результате шлют слишком много запросов с If-Modified-Since. С первым справляемся отрезанием самих Cookie, а со вторым — кешированием ответов 304 Not Modified. Напоследок же автор пытается эмулировать Cache-Control через отрезание Last-Modified, что уже напрямую идет вразрез RFC на HTTP/1.1 и скорее всего, чревато очередными граблями.
В итоге же все это комсомольское путешествие оказывается всего-лишь следствием одного из возможных решений специфической проблемы автора и совсем не обязательно разламывать управление кешированием HTTP из-за того, что какой-то программист однажды накосячил. Так что рекомендую воспринимать эту статью с хорошей долей grain of salt и думать самостоятельно о последствиях отключения чего-либо.
+1
По поводу истории — не угадали. :-) Были совсем другие грабли. Но насчет «самостоятельного думания» — Вы совершенно правы.
0
fastcgi_cache_key "$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri"; — это полный пэ. ладно бы оно было только на личном сайте автора, а так и на хабру попало, и по всему рунету расползлось… рекомендация по поводу восприятия этой статьи — лучшее что есть на этой странице вообще…
0
Кстати, в рассылку nginx предложили элегантное решение для Last-Modified. Оно работает, проверил. Я изменил статью соответствующим образом.
0
Only those users with full accounts are able to leave comments. Log in, please.
Подводные камни при использовании кэширования в nginx