Зачем кэшировать ответы на уровне Nginx
Кэш на уровне Nginx хранит уже готовый ответ бэкенда и отдаёт его напрямую при повторном запросе, не трогая PHP-FPM или прокси-приложение. Для сайта с высокой посещаемостью это снимает основную нагрузку с CPU и базы данных: страница блога или карточка товара, которая не меняется каждую секунду, рендерится один раз, а дальше отдаётся из памяти или с диска.
Есть два типа кэша с одинаковой логикой, но разными источниками: proxy_cache кэширует ответы, полученные через proxy_pass (см. статью про reverse proxy), а fastcgi_cache — ответы от PHP-FPM, полученные через fastcgi_pass. Настройка обеих директив почти идентична.
Настройка зоны кэша
Зона кэша объявляется один раз в блоке http и задаёт, где хранятся файлы и сколько памяти выделено под индекс ключей.
proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=proxy_cache:10m max_size=1g inactive=60m use_temp_path=off;
keys_zone=proxy_cache:10m — имя зоны и объём памяти под метаданные, примерно 8000 ключей на 1 МБ. max_size=1g ограничивает размер кэша на диске, inactive=60m удаляет файлы, к которым не обращались 60 минут, даже если они формально ещё не устарели.
Использование proxy_cache в location
Внутри server-блока зона подключается директивой proxy_cache, а время жизни ответа — директивой proxy_cache_valid.
location / {
proxy_pass http://127.0.0.1:3000;
proxy_cache proxy_cache;
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
add_header X-Cache-Status $upstream_cache_status;
}
Заголовок X-Cache-Status — самый быстрый способ отладки: значения HIT, MISS, EXPIRED и BYPASS сразу показывают, был ли ответ взят из кэша. Без этого заголовка догадаться о работе кэша можно только по времени ответа, что менее надёжно.
fastcgi_cache для сайтов на PHP
Для WordPress, Bitrix и других CMS на PHP-FPM кэш настраивается аналогично, только через fastcgi_cache и с ключом, который учитывает метод и куки.
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fcgi_cache:10m max_size=1g inactive=60m;
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_cache fcgi_cache;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_valid 200 10m;
fastcgi_cache_bypass $cookie_PHPSESSID;
fastcgi_no_cache $cookie_PHPSESSID;
}
Про сам путь настройки связки Nginx с PHP-FPM — в статье про Nginx и PHP-FPM. Кэшировать страницы для залогиненных пользователей обычно не нужно: fastcgi_cache_bypass и fastcgi_no_cache по кукам сессии исключают личный кабинет из общего кэша.
Параметры кэша: что за что отвечает
| Директива | Назначение |
|---|---|
| proxy_cache_valid | время жизни ответа с конкретным кодом статуса |
| proxy_cache_key | формула ключа, по которому ищется запись в кэше |
| proxy_cache_bypass | условие, при котором кэш не читается |
| proxy_no_cache | условие, при котором ответ не сохраняется в кэш |
| proxy_cache_lock | один запрос идёт на бэкенд, остальные ждут его результат |
proxy_cache_lock on; важен на старте прогрева кэша: без него сотня одновременных запросов к ещё не закэшированной странице отправит сотню одинаковых запросов на бэкенд разом, что и называют cache stampede.
Итог: чек-лист кэширования в Nginx
- Зона кэша создана директивой
proxy_cache_pathилиfastcgi_cache_pathв блоке http. - Время жизни задано отдельно для успешных и для ошибочных ответов.
- Страницы с куками сессии и личным кабинетом исключены через
*_no_cacheи*_bypass. - Заголовок
X-Cache-Statusдобавлен для отладки и виден в ответе curl. - Включён
proxy_cache_lock, чтобы избежать одновременных запросов на холодный кэш.