Кеширование в Nginx: как кешировать ответы бэкенда
Практика3 минРедакция Innovialabs
Коротко
Объявите зону кеша через proxy_cache_path, включите proxy_cache и proxy_cache_valid, исключите авторизованных пользователей через proxy_cache_bypass и proxy_no_cache, а proxy_cache_use_stale позволит отдавать сайт даже при падении бэкенда.
Короткий ответ
proxy_cache — это кеш Nginx на диске для ответов вашего бэкенда. Повторный запрос к той же странице отдаётся из кеша, и приложение вообще не вызывается. Базовая настройка состоит из двух частей:
# в блоке http
proxy_cache_path /var/cache/nginx/app levels=1:2 keys_zone=app_cache:10m
max_size=1g inactive=60m use_temp_path=off;
server {
location / {
proxy_pass http://app_backend;
proxy_cache app_cache;
proxy_cache_valid 200 301 10m;
proxy_cache_valid 404 1m;
add_header X-Cache-Status $upstream_cache_status;
}
}
- keys_zone — имя и размер зоны в памяти, где хранятся ключи и метаданные.
- max_size — предел места на диске; старые записи удаляются автоматически.
- inactive — запись удаляется, если к ней не обращались это время, даже если она ещё «свежая».
- proxy_cache_valid — сколько хранить ответы с конкретными кодами.
Заголовок X-Cache-Status показывает HIT, MISS, BYPASS, STALE и другие статусы — так удобно проверять работу кеша через curl -I.
Ключ кеша
Ключ определяет, какие запросы считаются «одинаковыми». По умолчанию это $scheme$proxy_host$request_uri. Если за одним upstream стоят несколько доменов, явно включите хост:
proxy_cache_key "$scheme$request_method$host$request_uri";
Добавляйте в ключ всё, от чего зависит ответ: например, язык, если он определяется по cookie, а не по URL. Иначе пользователь получит страницу на чужом языке.
Не кешируйте авторизованных пользователей
Главный риск кеширования — показать одному пользователю персональные данные другого. Для запросов с cookie сессии кеш нужно обойти и при чтении, и при записи:
proxy_cache_bypass $cookie_sessionid $http_authorization;
proxy_no_cache $cookie_sessionid $http_authorization;
- proxy_cache_bypass — не брать ответ из кеша.
- proxy_no_cache — не сохранять ответ в кеш.
Если любая из переменных не пустая и не равна 0, правило срабатывает. Также не кешируйте /admin, корзину, оформление заказа и API с персональными данными — проще вынести их в отдельные location без proxy_cache.
Учтите, что Nginx по умолчанию учитывает заголовки бэкенда: ответы с Set-Cookie или Cache-Control: private, no-store в кеш не попадают. Это защитный механизм, и отключать его через proxy_ignore_headers стоит только понимая последствия.
Отдача устаревшего кеша при сбоях
Кеш может спасти сайт, когда бэкенд упал или перегружен:
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
- proxy_cache_use_stale — при ошибке бэкенда отдать устаревшую копию вместо ошибки.
- updating вместе с proxy_cache_background_update — пока запись обновляется в фоне, пользователи получают старую версию без ожидания.
- proxy_cache_lock — при промахе к бэкенду идёт только один запрос, остальные ждут его результат. Это защищает от лавины запросов, когда популярная запись истекла.
Как очищать кеш
Директива proxy_cache_purge есть только в коммерческой NGINX Plus. В бесплатной версии используют другие подходы:
| Способ | Как работает | Минусы |
|---|---|---|
| Короткий TTL | Данные сами обновляются через несколько минут | Изменения видны не сразу |
| Принудительное обновление | proxy_cache_bypass $http_x_refresh — запрос с заголовком перезаписывает запись | Заголовок нужно защитить от посторонних |
| Удаление файлов | Очистить каталог кеша целиком | Сбрасывается весь кеш |
| Сторонний модуль | Например, ngx_cache_purge | Нужна сборка Nginx с модулем |
| Версии в URL | Для статики: app.3f2a.js | Подходит только для ассетов |
Для контентных сайтов чаще всего хватает комбинации короткого TTL и proxy_cache_use_stale: страницы быстро обновляются, а сайт остаётся доступным при сбоях.
Частые ошибки
- Кешируют страницы с персональными данными — самая опасная ошибка.
- Нет
X-Cache-Status, и непонятно, работает ли кеш вообще. - Ключ не включает хост или язык — пользователи видят чужие версии страниц.
- Каталог кеша недоступен для записи пользователю, под которым работает Nginx.