Когда бэкенд nginx перестаёт отвечать или возвращает ошибку 502 или 504, самый грубый результат для посетителя — страница ошибки вместо сайта. Директива proxy_cache_use_stale разрешает nginx в такой ситуации отдать устаревшую версию страницы из кеша вместо ошибки, пока бэкенд не восстановится. Это не чинит причину сбоя, а только продлевает жизнь сайта на время, пока она устраняется.
Что значит stale и чем это отличается от обычного кеша
Обычный кеш в nginx, настроенный директивами proxy_cache_valid, живёт до истечения срока, а затем запрос снова идёт на бэкенд за свежим ответом. Если бэкенд в этот момент недоступен, то без дополнительных директив запрос просто завершится ошибкой — кеш для этого конкретного ответа уже устарел и не используется автоматически.
Базовая настройка зоны кеша и времени жизни описана в статье про proxy_cache и fastcgi_cache. proxy_cache_use_stale добавляется к этой настройке и говорит nginx: при перечисленных условиях ошибки отдавай именно устаревшую запись, а не код ошибки.
Настройка proxy_cache_use_stale
Директива принимает список условий, при которых используется устаревший кеш: error — бэкенд недоступен или оборвал соединение, timeout — не ответил за proxy_read_timeout, updating — запись уже обновляется другим запросом, а также конкретные коды ответа http_500, http_502, http_503, http_504.
Условие updating особенно полезно вместе с proxy_cache_lock: пока первый запрос обновляет кеш, остальные получают старую версию страницы вместо того, чтобы ждать в очереди или одновременно бить по бэкенду. Сам location, где это добавляется, обычно уже существует в server-блоке, настроенном по статье про настройку Nginx для сайта на VDS.
proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=proxy_cache:10m max_size=1g inactive=60m use_temp_path=off;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_cache proxy_cache;
proxy_cache_valid 200 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;
}
proxy_cache_background_update и фоновое обновление
Несколько директив здесь работают вместе, и их легко перепутать по названию.
| Директива | Что делает |
|---|---|
| proxy_cache_use_stale | разрешает отдать устаревшую запись при перечисленных ошибках бэкенда |
| proxy_cache_background_update | обновляет устаревшую запись в фоне, пока клиент получает старую версию |
| proxy_cache_lock | не даёт нескольким запросам одновременно идти на бэкенд за одной и той же записью |
| inactive | время, после которого неиспользуемая запись удаляется из кеша на диске |
Если нужно диагностировать именно факт падения бэкенда, а не разбираться в показаниях X-Cache-Status, то конкретные причины 502 и 504 разбираются в статье про диагностику 502 и 504.
Ограничения: сколько живёт устаревшая копия
proxy_cache_use_stale не продлевает запись бесконечно — она всё ещё удаляется по директиве inactive, если к ней не обращаются. Если бэкенд упал надолго, а трафика на эту страницу нет, устаревшая копия может исчезнуть из кеша раньше, чем бэкенд восстановится.
Контент, который обновляется у каждого запроса — остаток товара на складе, баланс личного кабинета — не стоит отдавать как устаревший без явного предупреждения пользователю: для таких страниц надёжнее не кешировать их вовсе, чем показывать неверные цифры при сбое.
Чек-лист перед включением stale-кеша
Перед тем как включать proxy_cache_use_stale на продакшене, стоит свериться со следующими пунктами.
- Зона кеша и proxy_cache_valid уже настроены и проверены в нормальном режиме, без ошибок бэкенда.
- Для статических и слабо меняющихся страниц заданы длительные значения inactive, чтобы устаревшая копия не исчезала из кеша слишком быстро.
- Включён proxy_cache_lock, чтобы восстановление бэкенда не встретило лавину одновременных запросов на одну и ту же страницу.
- Страницы с персональными данными и актуальными ценами исключены из этого кеша через proxy_no_cache.
- Мониторинг проверяет значение X-Cache-Status на STALE отдельно от HIT, чтобы видеть, когда сайт работает на старых данных.
Частые вопросы
Видит ли посетитель, что ему показали устаревшую страницу?
Nginx не добавляет видимого предупреждения на саму страницу — отличить STALE от обычного HIT можно только по заголовку X-Cache-Status в ответе. Если важно показать пользователю предупреждение, его добавляют на уровне приложения или через отдельный баннер, который проверяет этот заголовок.
Что если бэкенд вообще никогда не отвечал для этой страницы?
Если записи в кеше ещё не было, proxy_cache_use_stale не поможет — отдавать нечего. Директива работает только с уже существующей, хотя бы раз закэшированной копией ответа.
Нужен ли proxy_cache_background_update, если уже включён proxy_cache_lock?
Да, это разные механизмы: proxy_cache_lock ограничивает число одновременных запросов на бэкенд, а proxy_cache_background_update решает, кто обновляет запись — текущий клиент, ожидающий ответа, или отдельный фоновый запрос, пока остальные получают старую версию без ожидания.