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=):

/b7f54b2df7773722d382f4809d650ab0

max_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;
    }
}

Обо всех директивах можете прочитать в оф. доке Директивы модуля ngx_http_fastcgi_module.

Тестирование

Перезагружаем 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» на что-то своё, чтобы скрипткидесы не баловались.

Полезные материалы

Вот небольшой список статей, который вам могут пригодится:

  • Директивы модуля ngx_http_fastcgi_module (оф. документация)
  • Описание модуля NginxHttpFcgiModule на wiki.nginx.org
  • Кеширование FastCGI-запросов в nginx
  • 56. Подводные камни при использовании кэширования в nginx
  • Nginx. Использование PHP в режиме FastCGI с помощью php-fpm

Понравилась статья, расскажи о ней друзьям, нажми кнопку!