# Кешування в Nginx: proxy_cache і fastcgi_cache на практиці

> Як налаштувати кешування в Nginx через proxy_cache і fastcgi_cache: зона кешу, ключ, час життя і скидання кешу для окремих сторінок.

## Навіщо кешувати відповіді на рівні Nginx

Кеш на рівні Nginx зберігає вже готову відповідь бекенду і віддає її напряму при повторному запиті, не чіпаючи PHP-FPM чи проксі-застосунок. Для сайту з високою відвідуваністю це знімає основне навантаження з CPU і бази даних: сторінка блогу чи картка товару, яка не змінюється щосекунди, рендериться один раз, а далі віддається з пам'яті або з диска.

Є два типи кешу з однаковою логікою, але різними джерелами: `proxy_cache` кешує відповіді, отримані через `proxy_pass` (див. статтю про [reverse proxy](https://www.zevshost.net/uk/kb/nginx-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](https://www.zevshost.net/uk/kb/nginx-php-fpm-svyazka/). Кешувати сторінки для залогінених користувачів зазвичай не потрібно: `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`, щоб уникнути одночасних запитів на холодний кеш.

---

Джерело: https://www.zevshost.net/uk/kb/nginx-proxy-cache-keshirovanie/
