Nginx. Кеширование с помощью fastcgi_cache
Устал я от того что мой блог долго грузится, но менять движок с WordPress на что-либо другое пока нет времени, а переезд на новый более мощный сервер всё время затягивается и решил прикрутить кеширование на стороне Nginx. Так как блог работает на fastcgi, то буду использовать fastcgi_cache, если вы используете связку Nginx+Apache, то вам следует использовать proxy_cache, как я понял там отличий особых нет.
Некоторые блоки мне всетаки надо оставить вне кеша, поэтому буду использовать ssi.
Настройка
У меня много хостов на одном сервере, но мне надо настроить кеш только для одного хоста. Определим кеш для моего блога в nginx.conf, секция http:
fastcgi_cache_path /var/cache/nginx/adw0rd levels=1:2 keys_zone=adw0rd:16m max_size=256m inactive=1d;
Где,
fastcgi_cache_path — путь до каталога кеша, создайте его заблаговременно.
levels= — разделять файлы кеша на сабкаталоги заданного уровня, то есть «1:2» — это так:/0/ab/b7f54b2df7773722d382f4809d650ab0либо так, если не указывать LEVEL, то есть levels оставить пустым (levels=):
/b7f54b2df7773722d382f4809d650ab0max_size — максимальный размер кеша.
incative — время жизни кеша.
Настройка виртуального хоста
Я разделяю конфиги на основной (nginx.conf) и на хосты (adw0rd.conf, pyha.conf, etc). Сейчас мы разберемся с adw0rd.conf:
server { # Порт который слушаем listen 80; # Имя хоста server_name adw0rd.ru; # Путь до htdocs (document_root) root /path/to/www; # включаем использование ssi ssi on; location / { # Если такой файл не существует физически, то переходить на крайний аргумент, то есть @wordpress try_files $uri @wordpress; } # обработчик для wordpress location @wordpress { # Проксируем на php-fpm fastcgi_pass php-fpm; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_param SCRIPT_NAME /index.php; # Настройки кеширования fastcgi_temp_path /tmp/nginx 1 2; # Каталог для хранение временных файлов fastcgi_cache adw0rd; # Имя зоны кеша fastcgi_cache_key "$request_method|$host|$request_uri"; # Из этих данных строится хеш fastcgi_hide_header "Set-Cookie"; # Не передавать клиенту заголовки кук fastcgi_cache_min_uses 1; # Кол-во запросов, после которых ответ будет закеширован fastcgi_cache_valid 10m; # Время жизни кеша fastcgi_cache_use_stale error timeout invalid_header http_500; # Случаи при которых будет использоватся старый кеш } # обработчик для динамических данных на странице, ниже я покажу как юзать это location ~ ^/ssi/ { fastcgi_pass php-fpm; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # Обработчик *.php файлов, например "wp-comments-post.php" location ~ .php$ { # если файл физически не существует, то переходим в @wordpress try_files $uri @wordpress; # иначе обрабатываем запрос fastcgi_pass php-fpm; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
Обо всех директивах можете прочитать в оф. доке [urlspan]Директивы модуля ngx_http_fastcgi_module[/urlspan].
Тестирование
Перезагружаем Nginx:
nginx -s reload
Для тестирования кеша я встроил в шаблон html-комментарий, который формирую так:
<!-- cache: <?php echo time() ?> -->
И теперь вижу в сорце странице закешировалась страница или нет.
Вставка динамических блоков при помощи SSI
Отредактируйте шаблон своей страницы и вставьте нечто подобное:
<!-- uncached_data: <!--# include virtual="/ssi/uncached.php" wait="no" --> -->
Теперь приведите файл «/ssi/uncached.php» к следующему виду:
<?php echo time();
Так как у нас есть обработчик действующий для /ssi/* и он не отдает кешированные данные, то у нас будет подгружатся динамика, все просто!
Дополнение
Директива fastcgi_ignore_headers для игнорирования инструкци от FastCGI-сервера
Директива fastcgi_ignore_headers запрещает обработку некоторых строк заголовка из ответа FastCGI-сервера. В директиве можно указать строки «X-Accel-Redirect», «X-Accel-Expires», «Expires» и «Cache-Control».
fastcgi_ignore_headers Expires Cache-Control;
То есть указываем Nginx кэшировать страницы в любом случае, независимо от заголовков кэширования выставленных FastCGI-сервером.
Директивы fastcgi_cache_bypass и fastcgi_no_cache
Директива задаёт условия, при которых ответ не будет браться из кэша. Если значение хотя бы одной из строк переменных не пустое и не равно «0», то ответ не берётся из кэша:
fastcgi_cache_bypass $cookie_session $cookie_nocache;
Директива задаёт условия, при которых ответ не будет сохраняться в кэш. Если значение хотя бы одной из строк переменных не пустое и не равно «0», то ответ не будет сохранён:
fastcgi_no_cache $cookie_session $cookie_nocache;
Управление кеширование через заголовок X-Accel-Expires
Будем управлять кеширование из PHP:
<?php header("X-Accel-Expires: $seconds"); // ставим на $seconds секунд header("X-Accel-Expires: 0"); // или отключаем кеширование для определенной страницы
Принудительное обновление кэша
Обновим наш bypass, добавим еще одну переменную для заголовка «X-Update»:
fastcgi_cache_bypass $cookie_session $http_x_update;
Ну а теперь обновим кеш:
curl -s -o /dev/null -H "X-Update: 1" example.com
Как и рекомендуют авторы статьи необходимо изменить «$http_x_update» и «X-Update» на что-то своё, чтобы скрипткидесы не баловались.
Полезные материалы
Вот небольшой список статей, который вам могут пригодится:
- [urlspan]Директивы модуля ngx_http_fastcgi_module[/urlspan] (оф. документация)
- Описание модуля [urlspan]NginxHttpFcgiModule[/urlspan] на wiki.nginx.org
- [urlspan]Кеширование FastCGI-запросов в nginx[/urlspan]
- [urlspan]56. Подводные камни при использовании кэширования в nginx[/urlspan]
- [urlspan]Nginx. Использование PHP в режиме FastCGI с помощью php-fpm[/urlspan]