Тотальное кэширование бэкенда на APACHE + PHP 5.3 aka FCGI в фронтэнде NGINX

logo

Тотальное кэширование бэкенда на APACHE + PHP 5.3 aka FCGI в фронтэнде NGINX Кэширование в NGINX для анонимных и зарегистрированных пользователей. Кэширование контента в фронтэнде NGINX помогает существенно снизить нагрузку на бэкенд, а соответственно и на весь сервер в целом...

Превед, люби друзи:) Сегодня вашему вниманию представляется очередной, НЕ тупая копи/паста, шедевр. Итак..., в этом посте не будет идти речь про установку APACHE + PHP 5.3 aka FCGI и подразумевается, что APACHE + PHP 5.3 aka FCGI уже установлен, настроен и теперь мы хотим замутить тотальное кэширование контента в фронтэнде NGINX для анонимных и не кэшировать его для зарегистрированных пользователей, для зарегистрированных пользователей будет достаточно внутреннего кэша самой CMS и внутренних акселераторов типа eAccelerator или APC имхо еже зарегистрированные пользователи должны получать как можно более актуальное содержимое сайта!

ВЫНИМАНИЕ!:) Кэширование в nginx настраивается отдельно для каждого из модулей fastcgi и proxy, ниже мы рассматриваем настройку для модуля proxy, а чтобы всё это работало и для fastcgi, то нужно везде изменить proxy_cache* на fastcgi_cache* соответственно!

Мана по настройке кэширования в NGINX в сети валом, вот например "Куроводство | Наблы | 56. Подводные камни при использовании кэширования в nginx", по которым можно настроить кэширование в NGINX, но не факт, что оно будет работать должным образом. Разбор полётов начнём с проблем...

NGINX не кэширует

Стою на асхвальте у лыжи обутый:)...


Так например в посте по упомянутой выше ссылке, да и не только в нём, рекомендуется использовать директиву proxy_cache_key следующим диким образом:

proxy_cache_key "$request_method|$http_if_modified_since|$http_if_none_match \
    |$host|$request_uri";

При этом приводится мутная, не до конца ясная и полная, аргументация необходимости использования, иногда встречается бред такого вида:

proxy_cache_key "$is_args|$request_method|$http_if_modified_since \
    |$http_if_none_match|$host|$request_uri";

При такой конфигурации значений в proxy_cache_key, nginx не будет кэшировать контент, вернее кэшировать будет ибо каталог с кэшем постоянно будет наполнятся, а эффекта от этого будет ноль!;( Как понять что нет эффекта от кэширования? Да очень просто, например повесить на сайт динамический модуль (к примеру модуль ротации баннеров) с обновлением раз в 15 минут при этом время жизни кэша в nginx установить равным в 1h, т.е. в 1 час и понаблюдать меняются ли баннеры или ещё проще, создать временный ХТМЛ файл и однократно обратится к нему через браузер, потом удалить его с сервера и обратиться повторно к уже не существующему файлу.

Бредовость выше описанной комбинации значений proxy_cache_key упоминалась здесь >>> Согласно оф. документации значение директивы proxy_cache_key близко к такой строке $scheme$proxy_host$uri$is_args$args. Список и описание переменных NGINX мы найдём тут >>>

Самым лучшим вариантом будет вовсе не определять proxy_cache_key! NGINX сам знает, что ему кэшировать, а если сильно хочется определить proxy_cache_key, то на худой конец можно попробовать использовать такую комбинацию:

proxy_cache_key "$scheme$proxy_host$uri$is_args$args|$scheme$host$request_uri";

Повторюсь - наличие файлов в директории /var/cache/nginx/pagecache, размер которой можно проверить командой du -shc /var/cache/nginx/pagecache/, не говорит о том, что клиенту в браузер отдаётся реально кэшированный контент!

Кэширование может не работать из-за proxy_buffering off отключенной буферизации ответов проксируемого сервера. Указываем явно proxy_buffering on, а также игнорируем заголовок "X-Accel-Buffering" через значение которого в off буферизация ответов проксируемого сервера может быть отключена.

Так в proxy_ignore_headers должны быть проигнорированы следующие заголовки: "Set-Cookie" "Cache-Control" "Expires" "X-Accel-Buffering", а иначе лыжи не поедут - т.е. кэш будет расти, а контент всё равно будет браться с "бакэнда"!!! Ещё важно добавить страницу авторизации в исключения кэширования директивой proxy_cache_bypass /URL /OTHER_URL иначе кукиши будут проигнорированы директивой proxy_ignore_headers и не смогут быть установлены!.

Обойти УРЛ с параметрами через proxy_cache_bypass и proxy_no_cache не удалось, хоть и в официальной  документации сказано что эти директивы принимают строку, а какую строку? - догадайся сам! Пришлось в ссылку для авторизации добавить аргумент &nocache=true, его же прописать в шаблонах форм авторизации (guests.denied.php, frontpage.guests.php, mobile.login.php, block.unregistered.php, mod_login) и обходить кэширование страниц авторизации через "proxy_cache_bypass $arg_nocache;" и "proxy_no_cache $arg_nocache;" соответственно - хотя товарищ Сысоев на своём форуме и заявлял, что мол POST запросы не кэшируются, но видимо всё вплоть до наоборот..., раз приходится обходить кэширование POST форм (вернее УРЛ-ов) авторизации, а иначе авторизации.нет;((.

Если учесть упомянутые выше нюансы, то кэширование в NGINX работает замечательно без необходимости дополнительных телодвижений. В редких случаях возможно будет полезным очистка заголовков If-Modified-Since и If-None-Match:

proxy_set_header  If-Modified-Since  "";
proxy_set_header  If-None-Match      "";

Ещё иногда NGINX не кэширует когда присутствует файл /etc/nginx/conf.d/default.conf - переименуйте его mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak.

Кэширование в NGINX для анонимных и зарегистрированных пользователей

Для кэширования в NGINX для анонимных и зарегистрированных пользователей можно использовать несколько вариантов с проверкой наличия кукишей с определённым именем:

proxy_no_cache $cookie_name;
proxy_cache_bypass $cookie_name;

В примере выше контент не будет кэширован proxy_no_cache и не будет браться из кэша proxy_cache_bypass если установлен кукиш с именем "name". Ещё один извратный вариант кэширования в NGINX только для анонимных:

if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" )
{
    set $nocache 1;
}
proxy_no_cache $nocache;
proxy_cache_bypass $nocache;

Можно также отключать кэширование при наличии определённых HTTP заголовков или аргументов (строки запроса), дополнительно гульчитаем в документации

После редактирования vi /etc/nginx/nginx.conf, сохраняем его и перезапускаем сервер service nginx restart, а также можем протестировать новую конфигурацию ab -n 1000 -c 100 http://www.mysite.com/

И под занавес немного о параметре keys_zone=pagecache:15m... Как правильно рассчитать keys_zone? На некоторых сайтах часто встречается не верное трактование сего параметра, а именно говорится о том, что в keys_zone указывается размер кэша который хранится на диске - это ошибка! В keys_zone определяется размер разделяемой оперативной памяти для более оперативной обработки поступающих запросов, а размер дискового кэша определяется в max_size=500m.

Все хитросплетения директив NGINX кэширования и его обхода для авторизированных и анонимных пользователей (для форм авторизации) отработаны путём многочисленных проб/ошибок, выложены в ниже приведённом конфиге NGINX vi /etc/nginx/nginx.conf работающем на нашем серванте:

 

Если в Apache .htaccess используется склейка доменов по редиректу 301, то директива proxy_redirect off; должна обязательно присутствовать в /etc/nginx/nginx.conf иначе когда чел обратится по адресу http://www.mysite.com/, а редирект его перекинет на http://mysite.com/, т.е. уже без www., то ответ 301 Moved Permanently будет закэширован и будет отображаться вместо главной страницы на протяжении времени валидности кэша!:)

Ссылки по теме

Олег Головский

Рекомендуемый контент

Добавить комментарий

АХТУНГ! Все комменты модерасятся модерастом. Мессаги исключительно рекламного или оскорбительного содержания не публикуются, а поэтому злостным спамерам, пранкерам и прочей сетевой нечисти рекомендуем напрасно не тратить своего времени и удовлетворять свои больные фантазии на специализированных Интернет ресурсах! Разумная же критика, замечания, дополнения и хвалебные оды приветствуются, также допускается легкий флуд или троллинг :)


Защитный код
Обновить

Новое на форуме