# конспект · шаг 6 из 6
Конспект: кеш ответов бэкенда
Кеш ответов бэкенда: две сущности, три таймера и одна ловушка с ключом.
Устройство
# зона в памяти + файлы на диске
proxy_cache_path /var/cache/nginx/api levels=1:2 keys_zone=API:10m
inactive=60m max_size=2g;
location /api/ {
proxy_cache API;
proxy_cache_valid 200 302 10m; # успешные - на 10 минут
proxy_cache_valid 404 1m; # отрицательные - чтобы не долбить бэкенд
proxy_pass http://app:8000;
}
Без proxy_cache_valid кеш не работает - nginx не знает, сколько ответ
считать свежим (если бэкенд сам не прислал Cache-Control).
Три таймера, которые путают
| Параметр | Смысл |
|---|---|
proxy_cache_valid |
сколько ответ считается свежим |
inactive (в proxy_cache_path) |
сколько запись живёт без обращений |
max_size |
сколько всего места под кеш |
Запись с valid 10s и inactive 60m протухнет через 10 секунд, но останется на
диске - и пригодится, когда бэкенд ляжет. И наоборот: популярная страница с
valid 1h вылетит из кеша, если к ней час никто не пришёл.
Что должно быть в конфиге кеша
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_min_uses 2; # не кешировать одиночные запросы
proxy_cache_bypass $http_pragma $cookie_session; # когда НЕ отдавать из кеша
proxy_no_cache $cookie_session; # когда НЕ класть в кеш
proxy_cache_use_stale error timeout updating http_500 http_502 http_503;
proxy_cache_lock on; # набег на истечении - один запрос к бэкенду
proxy_cache_background_update on;
add_header X-Cache-Status $upstream_cache_status always;
Ловушки джокера
- Ключ с
$uriвместо$request_uriотбрасывает строку запроса:?page=2и?page=3получат один и тот же ответ. - Кеширование персональных ответов. Без пары
bypass+no_cacheчужая корзина уедет соседнему пользователю - это самая дорогая ошибка раздела. Set-Cookieот бэкенда отключает кеширование ответа; если это мешает - убирают заголовок осознанно, а не «чтобы заработало».- Баг связки
proxy_cache_revalidateс HTTP/2-бэкендом починен в 1.31.3.
Что показал стенд
| опыт | результат |
|---|---|
proxy_cache без proxy_cache_valid |
три MISS подряд, три обращения к бэкенду |
с proxy_cache_valid 200 10s |
MISS, HIT, HIT - одно обращение |
бэкенд прислал Cache-Control: max-age=60, valid не задан |
MISS, HIT - кеш работает от заголовка |
ответ с Set-Cookie или no-store |
MISS, MISS - не кешируется |
ключ по $uri, запрос ?page=2 |
HIT с содержимым ?page=1 |
proxy_cache_min_uses 3 |
MISS, MISS, MISS, HIT |
бэкенд остановлен, use_stale против его отсутствия |
200 STALE против 502 EXPIRED |
| десять одновременных запросов на пустой ключ, ответ 2 с | без cache_lock 10 обращений, с ним 1 |
| прогретый кеш, перезапуск nginx | запись остаётся HIT - кеш переживает рестарт |
Ловушки джокера
proxy_cacheбезproxy_cache_validне кеширует ничего - и это первая ловушка при знакомстве.- Срок задаётся в двух местах: заголовок бэкенда работает сам, поэтому приложение может незаметно переопределить конфиг в обе стороны.
- Сокращённый ключ склеивает разные страницы в одну запись, и в логе при
этом честный
HIT. bypassбезno_cacheотправляет авторизованного мимо кеша, но его личный ответ туда всё равно запишется.proxy_ignore_headers Set-Cookieбезproxy_hide_header Set-Cookieраздаёт чужую сессию всем.- Кончается зона ключей, а не диск: 10 МБ - это около 80 тысяч записей.
use_staleне спасает то, чего в кеше нет - перед выкладкой кеш греют.proxy_cache_lock- про новые записи; набег на протухшую закрываютupdatingвuse_staleплюсbackground_update.
Комментарии
Пока нет комментариев. Будь первым!
Оставить комментарий