Настройка кэширования статики с помощью nginx в Debian

Лично мной настройка кэширования статики с помощью nginx в Debian задумывалась ради ускорения выдачи статического контента сайта на wordpress. Проблема возникла в том, что при использовании многосайтовой версии wordpress файлы хранятся в директории с длинным путём, при этом используется сокращение адреса за счет правил mod_rewrite. Для того, чтобы nginx выдавал статику, использовалась директива location с указанием расширений статических файлов и путь до директории со статикой:

location ~* \.(html|jpeg|jpg|gif|png|css|js|pdf|txt|tar)$ {
root /path/to/site/;
}

Недостаток схемы в том, что при добавлении изображений в посты приходилось вручную корректировать путь со сгенерированного автоматически на точный путь до файла.

Когда описанная выше ситуация утомила окончательно, было решено изменить используемый метод выдачи статики на кэширование. Фактически nginx продолжает выдавать статику, но уже прозрачно. То есть при обращении к файлу из списка используемых расширений он попадает в кэш nginx и при повторном запросе выдаётся уже из кэша напрямую без обращения к бэкенду. Попробуем описать как настроить кэширование в nginx с учётом обозначенной задачи.

Использовались ОС Debian 7.0, nginx 1.2.1. Предварительно следует обновить Debian.

Вообще говоря, все директивы указаны на официальном сайте nginx, но несколько тяжело для понимания.

Так как в основном конфиге /etc/nginx/nginx.conf имеем строку include /etc/nginx/conf.d/*.conf, то создаём отдельный файл /etc/nginx/conf.d/cache.conf с базовыми настройками кэша:

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=static_cache:100m inactive=120m max_size=500M;
proxy_cache_min_uses 1;

Разберём поэлементно первую строку, начинающуюся с proxy_cache_path. Таких строк может быть несколько, следовательно может быть несколько кэшей со своими параметрами и именами. Итак:

/var/cache/nginx - путь до директории с кэшем.

levels=1:2 - уровни директорий с кэшем. Уровни вложенности задаются через двоеточие, цифрами задаётся длинна имени директории. 1:2 говорит о том, что в директории с кэшем будут созданы директории длинной в одну шестнадцатеричную цифру (от 0 до f) в каждой из которых будут созданы директории с именами состоящими из двух шестнадцатеричных цифр.

keys_zone=static_cache:100m - задаётся имя кэша (static_cache) и его базовый размер в мегабайтах.

inactive=120m - время отсутствия запросов к элементу кэша, после которого он удаляется из кэша. В минутах. После этого, при запросе к тому же файлу, произойдёт запрос к бэкенду и файл снова попадёт в кэш.

max_size=500M - максимальный размер кэша в мегабайтах.

Вторая строка, как было выяснено экспериментально, также необходима для работы кэша nginx:

proxy_cache_min_uses 1; - указывает после какого количества запросов к файлу он попадёт в кэш.

Не забудьте создать директорию для кэша и задать для нее владельца от имени которого работает nginx в Debian:

mkdir /var/cache/nginx
chown www-data:www-data /var/cache/nginx

Затем в файле описания сайта в директории /etc/nginx/sites-available прописываем примерно следующее:

location ~* ^.+.(html|jpg|jpeg|gif|css|png|js|ico|gz)$ {
expires 60d;

proxy_pass http://backend;
proxy_redirect     off;

proxy_set_header   Host             $host;
proxy_set_header   X-Real-IP        $remote_addr;
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
proxy_cache static_cache;
proxy_cache_key "$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri";
proxy_cache_valid 1d;
}

В данном случае мы запросы также перенаправляем на бэкенд, но при этом кэшируем их на сутки. Нас интересуют следующие параметры:

proxy_cache static_cache; - указываем какой кэш использовать.

proxy_cache_valid 1d; - позволяет задать время кэширования для разных кодов ответа. По умолчанию кэшируются только ответы с кодами 200, 301 и 302.

proxy_cache_key "$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri"; - эта строка самая интересная. Она позволяет настроить по каким признакам считать, что следует кэшировать запросы отдельно. К примеру, значение в файле кэша nginx может выглядеть следующим образом:

GET|||droid.gesu.su|/wp-content/plugins/addthis/css/output.css?ver=3.5.1

Видно, что в данном случае

$request_method = GET
$host = droid.gesu.su
$request_uri = /wp-content/plugins/addthis/css/output.css?ver=3.5.1

То есть при использовании другого метода запроса файл нужно кэшировать отдельно. То же для одинакового имени для разных доменных имён или разных имён файлов для одного домена.

$http_if_modified_since и $http_if_none_match - позволяют не выдавать страницы с ответом “304 Not Modified” или пустые страницы. В нашем случае, это, скорее всего, не актуально, так как мы выдаём статический контент, который редко изменяется.

Ряд переменных, которые можно использовать в строке proxy_cache_key, можно найти в wiki nginx.

Вот, собственно и все, для нашего случая большего не нужно. Система кэширования довольно гибкая и позволяет кэшировать результаты конкретных страницы, отображаемых по конкретным запросам, что позволяет дополнительно снять нагрузку с бэкендов.

UPD. Если файлы в кэша не создаются и в логе присутствует строка:

http file cache: /var/cache/nginx 0.000M, bsize: 4096

То попробуйте увеличить значения буферов в блоке http:

proxy_buffers 8 2m;
proxy_buffer_size 10m;
proxy_busy_buffers_size 10m;

Ссылки

Наверх

Опубликовано