Pull to refresh

Comments 65

Спс. А как удобнее сбросить кеш, например, при изменении страницы через админку?
Для этого нужно proxy_no_cache заменить на

proxy_no_cache $cookie_session $http_x_update;

и при обновлении страницы через админку делать внутренний запрос к nginx без куки, но с заголовком X-Update: 1
Имхо при этом страница будет не закэширована, но сам кэш при этом не измениться
Если использовать не proxy_no_cache, а

proxy_cache_bypass $cookie_session $http_x_update;

то кеш будет обновляться. Только что проверил на 1.0.5.
Если у вас апдейты несрочные, то ставьте время жизни кеша в одну минуту.
Если Вы хотите удалять кэш из админки, Вы также можете добавить в секцию локейшн строку:
fastcgi_cache_key "$host$request_uri" или proxy_cache_key "$host$request_uri", смотря что Вы используете, и в указанной папке хранения кэша, кэш страниц будет лежать под именем:
md5($host.$request_uri).

Пример:
зайдя по ссылке: habrahabr.ru/blogs/nginx/124684/
кэш будет лежать в указанной папке с именем: md5('habrahabr.ru/blogs/nginx/124684/');
Сысоев обещал это приделать, но похоже руки так и не дошли.
Я лично убиваю кэш и рестартую nginx
Что значит не сделал? Я так делаю.
Как так? Удаляете файлы?
Речь шла о более удобных и правильных способах управлением кэшем — сигналом хотя бы или хитрым запросом.
А что Вам мешает реализовать свою схему очереди? Сделайте стек очередей и отправьте туда сигнал на удаление кэша, что Вам это мешает сделать?

А по поводу сигнала nginx-у, как? Он веть хранит файлы под хэшем, он не может пробежаться даже регулярке: site.zone/news/*.

Поэтому самому удалять это самый простой и не сильно уж и долгий процесс, тем более если Вы кэш будете хранить в памяти.
очереди чего?

у nginx-а есть понятие зоны для кэша. Меня вполне устроит сброс таймингов для зоны. Процесс же удаления зависит от количества удаляемого. С учетом того что для ускорения работы делают вложенность, то это совсем не равноценно сбросу некторых таймеров внутри сервера.

Тут мне пришла в голову мысль что может быть таймеры на самом деле — это время модификации файла/ключа. Надо будет попробовать их состарить в качестве сброса кэша.

Но все равно это не снимает вопроса в «первона#е» — как через админку сайта сбросить ему кэш. Приходиться рыться в конфигах и вытаскивать путь под doc_root-ом, что уже плохо. А потом там шерудить, что совсем не хорошо. Было бы намного удобнее иметь возможность задать ключ для сброса кэша в пределах действия proxy_cache — для location или server.
Типа пусть каждый занимается своим делом. Управлять кэшем — дело как раз для proxy модуля nginx, а не всяких приблудных скриптов.
Я не хочу и не буду с Вами спорить, я только озвучил как это делаю я.
Просто при администрировании у меня не нужно удалять весь кэш сайта, а всего кэш 1-10 страниц, которые лежат в памяти, как вы понимаете — это почти мгновенная операция.
Если страницы надо удалять из кэша поштучно, то есть модуль, который это дело делает (директива proxy_cache_purge), у меня настроена хитрая комбинация символов, их надо дописать в урл, чтобы удалить из кэша конкретную страницу.

Если массово, то зная список ссылок можно узнать список путей на диске (директива proxy_cache_key) и удалить их скриптом.
Правильно будет использовать директиву не proxy_no_cache, а

proxy_cache_bypass $cookie_session $http_x_update;

Например, можно поставить обновление главной страницы раз в минуту через curl:

curl -H "X-Update: 1" www.example.com
Что-то вы все переврали.
Объясню как есть на самом деле:
1. Nginx кеширует ответы от бэкэнда, которые он разрешил кешировать. Nginx смотрит на заголовки Cache-control, Expires.
2. В php, если стартует сессия, то автоматом добавляются заголовки
(само отправилось)
автоматом добавляются заголовки:
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Соответственно nginx такой ответ не закеширует.

3. Соответственно, как вы правильно сказали, чтобы кеш работал, не надо стартовать сессию.
А строчку «proxy_ignore_headers Expires Cache-Control;» как раз нужно убрать, тогда всё будет работать правильно — там где нет сессии и нет заголовков закешируется, там где есть заголовки будет без кеша.

Кстати
Если у вас есть время влезать в исходники какого-то случайно выбранного сайта, написанного бог знает когда бог знает кем — убирайте proxy_ignore_headers и ищите, где там в коде сайта задаются заголовки Cache-Control и Expires чтобы их убрать.

У меня на это времени и сил нет, в жизни есть занятия интересней, чем копаться в чужом коде без явной необходимости, которой здесь нет.
Если мы говорим о случайном проекте, в котором нет времени разбираться, тогда вы правы.
Можно использовать различные костыли.
спасибо за правильное объяснение
Вы не совсем правы, дело в том, что если у Вас отдаются изображения через тот же nginx, то у Вас возникнет такая ситуация, что все картинки будут тоже закешированны, т.к. он сам добавляет эти заголовки для браузера.
Сам столкнулся с подобной проблемой, не мог понять почему у меня уменьшался объем на ШДД, а nginx просто параллельно еще кешировал и сами изображения, тоесть просто копировал их в папку для кеша.
Для картинок лучше отдельный location без кеширования но с expires и всем, что нужно:
location ~* \.(jpg|jpeg|gif|png|ico|css|js|swf)$ {
expires max;
root /var/www;
}
Для статики вообще желательно использовать отдельный субдомен, чтобы не заставлять его бегать по регуляркам, я лично так делаю.

Конечно в локейшине можно и отключить его, просто я столкнулся с такой проблемой. а до этого не знал о этом, сейчас просто поделился.

Что касается приведенного Вами примера, он тоже не всегда хорош, у меня есть изображения которые гинерятся скриптом.
Про статику никто не говорил :)
Если статика на том же сервере, то её нужно выносить в отдельный локейшен, чтобы она бралась напрямую с диска, если она на другом серваке, то можно и закешировать, чтобы не гонять между серваками и не напрягать бэкендовый апач.
Поэтому proxy_ignore_headers Expires Cache-Control; желателен.
Прочитайте, пожалуйста, документацию в разделе про proxy_ignore_headers и ещё раз скажите мне: где я что переврал?
Вы пишете: нужно не стартовать сессию — это не совсем верно.
Т.к. дело не в сессии, а в заголовках, которые автоматом шлются при старте сессии.
Но ваш пример тоже работает.
На самом деле можно и не указывать proxy_cache_bypass $cookie_session; proxy_no_cache $cookie_session; т.к. nginx не кэширует если видит заголовок Set-Cookie. Да, в документации про это ни слова :)
Эти заголовки нужны чтобы клиенты, у которых в запросе есть заголовок Cookie с куки session проходили мимо кеша. К заголовку Set-Cookie эти директивы отношения не имеют.
еще раз. nginx по дефолту не будет кэшировать если увидит в ответе клиенту заголовок Set-Cookie внезависимости от того что там в proxy_no_cache. это поведение можно изменить добавив proxy_ignore_headers «Set-Cookie»;
И правильно делает. Зачем оно нужно — кешировать запросы в которых есть Set-Cookie? Вдруг это вы, пытаетесь зайти на сайт, чтобы оставить комментарий?
а может вы гуглобот и вам побоку на всякие куки, но вы приходите регулярно за одним и тем же :)
в общем я лишь хотел указать на избыточность proxy_no_cache $cookie_session; и на неполноту документации.
По этой схеме куки отправляются только при POST-запросах, а те по-умолчанию не кэшируются. Следовательно, мы ничего не теряем.
А если такая ситуация:
* Захожу на какую-то страницу типа about. Она кешируется
* Затем я логинюсь, страница логина не кешируется из-за Set-Cookie
* захожу снова на about — и получаю кешированную струницу??

А это не всегда желательный эффект, ведь где нибудь может быть написано Hello Guest / Hello yngvie
Тут уже проверяйте кукисы в конфиге nginx и если они есть, определенная кукиса, то не юзайте кэш.
Сложнее. Если кэшировать страницы с Set-Cookie, то вы получите куки другого пользователя, который входил на сайт до вас. Потому nginx по-умолчанию не кэширует запросы в которых есть Set-Cookie.
Так можно сделать кеш с куками для каждого отдельного юзера.
Сейчас мсто на хостингах резиновое, ssd, все дела.
proxy_cache_bypass $cookie_session; нужен
Старт сессии при POST-запросе? Ужасный совет. Сколько же проблем будет, когда об этом все забудут.
Конечно, особенно когда об этом забудут те разработчики, что писали пять лет назад некий сайт, внезапно ставший популярным. Если вы на своём сайте можете сделать правильно и если у вас есть время сделать как надо — этот совет не для вас.
Правильно нужно делать всегда. Отладка плохонаписанного кода или внесение в него новой функциональности занимеат куда больше веремени нежели написание правильного кода.
POST-запрос не означает начало новой сессии. Это допущение не верно. Кроме того, аутентификация может осуществляться и GET-запросом (напрмер OpenID).

А задача решается 2-мя фунциями/методами: get*/set*. get* получает значение из $_SESSION[], при этом, если сессия не существует, то ничего не стартуется, а возвращается какое-то пустое значение. set* устанавливает значение, при этом стартует сессию.
Задача так не решается если перед вами сайт, который написан бог знает когда, бог знает кем, а заказчик не заинтересован оплачивать ваше время на глубокую переработку сайта. Выше я писал что в жизни есть занятия интересней, чем копаться в чужом коде без явной необходимости, которой здесь нет, и тем более без оплаты. Вы готовы работать бесплатно? Я — нет.
Такие условия очень желательно оговаривать в статье.
В начале статьи написано что «редкий сайт нельзя довести.» Довести — значит изменить до определенного состояния (словарь Ушакова). Дальше написано о том, что этот метод применим к большинству сайтов. Большинство сайтов на PHP — сами знаете какое. По-моему всё должно быть понятно.
А зачем не стартовать сессию? Можно же просто при логине добавить куки LOGINED или там ADMIN и если она есть отдавать напрямую? По моему легче в метод авторизации добавить установку куки чем из всего сайта выпилить сессии — если я не админ это не значит что они мне не нужны.
Если вы не стартуете сессию, то как в вашем интернет-магазине будет работать корзина?
Этот рецепт подходит для любых сайтов, использующих штатные сессии.
Не совсем понял. Я же и спрашиваю как без сессий быть? хотя с другой стороны — изменилась сессия вероятнее всего и вывод изменился так что в принипе логично
Не надо быть без сессий. Надо не использовать их без нужды.
«Logined» — это на каком языке?
Gramar nazi? А мне так нравится:) оно из за того разве не скомпилится или не выполнится?
ну видите, не я один такой, уверен тут тоже половину это не удивило :)
UFO just landed and posted this here
Уговорили :) Теперь буду использовать только рассово верную форму LOGGEDIN. Скажите, а вы пользуетесь словом «гуглить», ведь «to google» сам не так давно стал verb'ом?
UFO just landed and posted this here
да и я без претензий :) кстати на гугловском кодесерче огромный перевес в сторону Loggedin :)
UFO just landed and posted this here
Для Django замените везде $cookie_session на $cookie_sessionid. Этого достаточно.
Есть один неприятный баг — если значение куки начинается с 0, то нгинкс ошибочно считает ее пустой. Для решения проблемы существует патч. Другой способ — просто генерировать правильный PHPSESSID.
В исходниках nginx 1.0.4 я вижу что эта проблема уже исправлена.
Нам нужно защитить его от всплесков посещаемости

Всплески посещаемости — это же хорошо, не надо от них защищать, надо к ним готовить =)
Это просто чудо какое-то!
Правда, не сразу получилось настроить — был затык на уровне прав записи юзера www-data в папку с кешем.
Но когда заработало, то всё залетало.

pS. Важно помнить (было выше в коментах), что ключ кеша строится как MD5(Url), поэтому если такой кеш настроить сразу на несколько сайтов, одиноковый УРЛ на разных сайтах будет давать одинаковый результат — ту страницу, что первой попала в кеш (например, индесная страница с УРЛом "/")
Хорошее замечание. Ключ хеша задается директивой proxy_cache_key
Sign up to leave a comment.

Articles