Вопрос по кеширования в nginx

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
В общем суть ситуации такая. Есть виртуальный сервер, поднятый на nginx+php-fpm. Все работает хорошо и свою задачу выполняет, но есть один неприятный момент.

Мы часто выкладываем обновления статичных файлов, то есть CSS/JS. Так как выкладываем мы их под старыми именами, то закешировавшись, они далее отдаются старыми, без проверки даты последнего изменения. При этом ломается view страницы напрочь. Чинится все банальным F5, но это не практичный вариант.

Как допилить конфиг?

Имеем конфиг:
Код:
server {
        listen   80;
        set $root '/var/www/xiio.local/www';
        server_name  xiio.local;
        expires -1M;

        root   $root;
        index  index.php index.html index.htm;

        access_log  /var/log/nginx/xiio.local.access.log;
        error_log   /var/log/nginx/xiio.local.error.log;

        location / {
            location ~* ^.+\.(ico|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
                error_log off;
                access_log off;
                # only set expires max IF the file is a static file and exists
                if (-f $request_filename) {
                    expires max;
                }
            }

            location ~* (.+\.tpl$) {
                deny all;
            }

            if (!-e $request_filename) {
                rewrite ^(.*)$  /index.php last;
            }
        }

        location ~ \.php$ {
                fastcgi_pass   unix:/tmp/php-fpm.sock;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  $root$fastcgi_script_name;
                include fastcgi_params;
        }
}
 

Dovg

Продвинутый новичок
1. С какими заголовками приходит запрос на статику ?
2. какие заголовки возвращает nginx с картинкой?

СОбственно строкой expires max; ты заставляешь кешировать навечно.
Если ее просто убрать, то кеширование там работает из коробки при помощи if-modified-since и last-modified
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Жмакнул F5 и получил:

Request Headers
Accept:text/css,*/*;q=0.1
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:xiio.local
If-Modified-Since:Wed, 26 Oct 2011 12:32:28 GMT
Referer:http://xiio.local/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Ubuntu/11.10 Chromium/14.0.835.202 Chrome/14.0.835.202 Safari/535.1

Response Headers
Cache-Control:max-age=315360000
Connection:keep-alive
Date:Wed, 26 Oct 2011 12:37:37 GMT
Expires:Thu, 31 Dec 2037 23:55:55 GMT
Last-Modified:Wed, 26 Oct 2011 12:32:28 GMT
Server:nginx

Если файл поменять и нажать F5
Status Code:200 OK
Request Headers
Accept:text/css,*/*;q=0.1
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:xiio.local
If-Modified-Since:Wed, 26 Oct 2011 12:32:28 GMT
Referer:http://xiio.local/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Ubuntu/11.10 Chromium/14.0.835.202 Chrome/14.0.835.202 Safari/535.1

Response Headers
Cache-Control:max-age=315360000
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/css
Date:Wed, 26 Oct 2011 12:38:46 GMT
Expires:Thu, 31 Dec 2037 23:55:55 GMT
Last-Modified:Wed, 26 Oct 2011 12:38:40 GMT
Server:nginx
Transfer-Encoding:chunked
Vary:Accept-Encoding
 

Dovg

Продвинутый новичок
убери expires max;
Если я правильно понимаю логику браузеров, то увидев Expires:Thu, 31 Dec 2037 23:55:55 GMT он может до 2037 года запрос даже не повторять, следовательно никак не узнает, что файл изменился.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Угу, убрал, заработало нормально, но судя по профайлеру типа который в firebug ему не хватает кеша на статике, послал firebug нахер...
 

MiksIr

miksir@home:~$
1. error_log off создает лог-файл с именем off
2. if -ы лучше заменить на try_files, expires max поднять в локейшн, и определить 404-й локейшн с отрицательным expires
Теперь по сути - для того, что бы гарантировать, что измнения сразу же пойдут клиенту, способ только один - менять имена (если точнее - приделывать query_string с датой изменения файла или ревизией по svn или еще что-то). Или же убрать expire. В ином случае - запрашивать сервер о том, изменился ли файл или нет - на совести браузера.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Опа, а вот про логи я что-то пропустил, так как раньше это вроде работало нормально.

Имена увы менять/присоединять к ним query string мы не хотим. Искали другое решение.
 

MiksIr

miksir@home:~$
По сути варианта два - или приставки или запрос на сервер про каждый файл (сам файл передаваться скорее всего не будет, если не менялся - 304-й ответ будет, но запрос будет).
И, кстати, убрать expires заменить на отрицательный - это даст гарантию запроса на сервер каждый раз. А вот убранный просто expires - вполне может использовать кеш на протяжении сессии.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
fixxxer
Наше решение

MiksIr
Я в курсе про отрицательный expires, тут задача была именно, не в отключении кеша совсем, а чтобы при модификации файла, при следующем запросе клиенту выдавался уже 200 ответ, а не 304
 

MiksIr

miksir@home:~$
При модификации файла оно всегда так будет. nginx по дефолту ставит Last-Modified, проверяет If-Modified-Since. Главное, что бы браузер пошел на сервер с этим вопросом. При убранном expires он ходит при первом посещении сайта, а потом уже не ходит - т.е. если вы поменяли что-то, а посетитель ходит по сайту - увидит косяк. При отрицательном - не исключаю, что зависит от браузера. Хром вот держит кеш сессии, и даже при отрицательном expires запрашивает If-Modified-Since и отрабатывает 304-й ответ.
 

fixxxer

К.О.
Партнер клуба
c0dex
Ну странное решение честно говоря. Вариантов остается всего один - заставить браузер заголовками _каждый_раз_ проверять If-Modified-Since + заставить все промежуточные кэширующие прокси не кэшировать ответ. В дополнение к expires тут как минимум еще надо Pragma: no-cache (Cache-Control вроде как nginx-овский expires ставит).

Алсо, от такого
Код:
                # only set expires max IF the file is a static file and exists
                if (-f $request_filename) {
                    expires max;
                }
...
            if (!-e $request_filename) {
                rewrite ^(.*)$  /index.php last;
            }
Сысоеву по ночам кошмары снятся. Лучше это убрать и отменять действие где оно не надо. А вместо реврайта try_files на именованный location.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
fixxxer
Я как бы вообще не админ, как сумел так сделал,раньше сервер вообще загибался с апачем. Мне бабки за это не платят, а платят админу удаленному, который не обновляет толком сервак.

Есть примеры как сделать - выкладывай, покручу, попробую, пока мне самому разбираться в написанном тобой - лень
 

fixxxer

К.О.
Партнер клуба
А я чото вот вообще теперь не пойму, зачем у тебя там стоят всякие expires - тебе ведь, получается, надо, чтобы вообще ничего в браузере не кэшировалось? Или я что то не понял?

Что касается админов - конфиг nginx - штука такая, что его должны писать и разработчик, и админ, и, соответственно, разбираться в нем оба: логику location-ов пишет программист, всякие настройки буферов, воркеров и sendfile-ов - админ. Такова жизнь, ничего не поделать )
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
fixxxer
Expires max; там стоял изначально на всю статику, по уму там надо все-таки не кешировать и проверять модификацию js/css, а не всех статичных файлов. Конфиг чутка попозже допилю.

Проблема состоит в том, что кроме меня с nginx никто близко не знаком у нас. А вот по поводу реврайтов - пример с инета, так что сон Игоря не на моей совести))
 

Dovg

Продвинутый новичок
Игорь иногда читает доклады о конфигурировании nginx. Точно было в Рамблере и на какой-то конференции. В интернете есть видео, но сейчас, к сожалению, не могу найти.
Рекомендую посмотреть. После него nginx гораздо лучше конфигурируется, т.к. начинаешь понимать, что принципы конфигурирования сильно отличаются от апача. Другими словами, мозги на место встают.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
У nginx есть одна самая большая беда - полнейшее отсутствие вменяемых примеров конфигов, то есть все директивы описаны весьма нормально, понятно в каких местах их ставить, но вот как их сочетать в готовом простом виде - хрен. Лично мне не хватает именно этого.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
это я в курсе

я имел в виду, чтобы краткие примеры были прямо в месте описания директив конфига
 

fixxxer

К.О.
Партнер клуба
c0dex

Вообще разделять по расширениям это не очень хорошая идея. Лучше разнести все по location-ам. Код отдельно, js/css/картинки оформления отдельно, пользовательские аплоады отдельно. Тогда конфигурация становится тривиальной.

Да и управлять кодом и деплоем намного удобнее, когда все это отдельно, а не в одной куче.
 
Сверху