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]