Перейти к содержанию
Innovialabs

Кеширование в Nginx: как кешировать ответы бэкенда

Практика3 мин

Коротко

Объявите зону кеша через 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.

Частые вопросы

Браузерный кеш хранится у каждого пользователя и управляется заголовками Cache-Control. proxy_cache хранится на вашем сервере и общий для всех посетителей, поэтому снижает нагрузку на бэкенд даже для новых пользователей.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.