Когда речь заходит о кэше в Nginx, почти все дороги ведут к директиве proxy_cache_path. От того, как вы выберете путь на диске, глубину каталогов, размер keys_zone и политику вытеснения через max_size/inactive, зависит производительность, долговечность носителя и предсказуемость отклика. В этой статье сосредоточимся на практическом понимании и безопасных пресетах для продакшена.
Зачем нужен proxy_cache_path и где его объявлять
proxy_cache_path объявляется в контексте http и определяет:
- путь на диске, где хранится кэш;
- структуру каталогов (
levels) для равномерного распределения файлов; - зону ключей в общей памяти (
keys_zone) — индекс кэша; - политику очистки и вытеснения:
max_sizeиinactive; - троттлинг фоновых задач загрузчика и менеджера кэша:
loader_files,loader_sleep,loader_threshold,manager_files,manager_sleep,manager_threshold.
Далее вы подключаете зону кэша через proxy_cache внутри server/location. Важно: одна зона ключей соответствует одному каталогу кэша и одному набору параметров менеджера/загрузчика.
Ключевая зона: keys_zone
keys_zone задаёт имя и объём общей памяти (shared memory), где хранятся метаданные кэша: ключи, атрибуты валидности, ссылки на файлы на диске. Без достаточного объёма зоны Nginx не сможет индексировать новые записи и начнёт обходить кэш. В логах это проявляется сообщениями наподобие: «could not allocate node in cache keys zone».
Оценка объёма: на практике 1 МБ зоны способен хранить примерно до 8 тысяч ключей. Это усреднённая оценка, учитывающая накладные расходы; реальные цифры зависят от длины ключей, количества вариаций по Vary, и архитектуры. Чтобы прикинуть размер:
- Определите ориентировочное количество одновременно живых объектов в кэше (working set). Например, 400 тыс.
- Разделите на 8 тыс. и умножьте на 1 МБ: 400000 ÷ 8000 × 1 МБ ≈ 50 МБ.
- Добавьте запас 30–100% на вариации размера ключей,
Varyи рост: получим 64–128 МБ.
Правило большого пальца: для небольших микрокэшей (API на секунды) начинайте с 16–64 МБ; для origin-кэша статики — 64–256 МБ; для больших CDN-ориджинов и медиатеки — сотни МБ и более.
levels: логическая разбивка каталогов
Параметр levels управляет тем, как Nginx раскладывает файлы по вложенным каталогам, используя хеш ключа. Цель — не допускать огромных каталогов с десятками тысяч файлов, где операции ОС становятся дорогими. Типичные варианты:
levels=1:2— подойдёт для сотен тысяч объектов;levels=2:2или2:2:2— для миллионов и десятков миллионов;- ориентируйтесь, чтобы в каждом каталоге было не более ~5–10 тыс. записей.
Менять levels на живом кэше нельзя без миграции — текущая структура каталога станет несоответствующей индексу. Планируйте заранее.
max_size: ограничение объёма на диске и поведение LRU
max_size ограничивает общий объём кэша на диске. Когда он достигнут, фоновой менеджер начнёт вытеснение старых/давно неиспользуемых записей (по сути, LRU-подобная эвикция с оглядкой на «последний доступ»). Выбор значения зависит от ёмкости файловой системы и профиля трафика:
- Если кэш на выделенном разделе — задайте 70–90% от свободного объёма, оставив место под служебные данные ФС и разовые всплески.
- Если кэш делит раздел с другими данными — будьте консервативны (30–50%).
- Эвикция — процесс постепенный. Не держите
max_sizeвплотную к объёму диска, иначе возможны спайки нагрузки менеджера и риск врезаться в 100% usage до начала очистки.
Учитывайте природу контента: для мелких API-ответов те же 50 ГБ — это колоссальный запас, а для видеосегментов по 2–8 МБ — наоборот, скромный объём.
inactive: когда удалять то, к чему не обращаются
inactive — это не TTL объекта, а период неиспользования. Если файл не запрашивали дольше, чем указано в inactive, он вычищается, даже если формальный TTL (по заголовкам или proxy_cache_valid) ещё не истёк. Это позволяет защититься от «мусора», который когда-то попал в кэш, но больше не востребован.
Практические ориентиры:
- Микрокэш для API:
inactive10–60 секунд (агрессивно чистить). - Кэш статики с fingerprint-именами: 7–30 дней (редко запрашиваемые файлы выпадут сами).
- Медиаконтент или архивы: от часов до дней, зависит от закономерностей повторных обращений.
TTL кэша задают заголовки upstream либо директивы типа
proxy_cache_valid.inactiveдополняет TTL, удаляя то, к чему не было запросов достаточно долго. Эти механизмы работают совместно.

loader и manager: как не убить диск при запуске
При старте Nginx нужно «поднять» индекс кэша в память: просканировать каталог, загрузить метаданные в keys_zone. Этим занимается загрузчик (loader). Фоновый менеджер (manager) следит за max_size/inactive и делает очистку. Чтобы избежать пиковых штормов I/O, используйте троттлинг:
loader_files— сколько файлов загружать за один проход.loader_sleep— пауза между проходами.loader_threshold— максимальная длительность одного прохода.manager_files— сколько файлов обрабатывать за один проход очистки.manager_sleep— пауза между циклами менеджера.manager_threshold— предельная длительность цикла менеджера.
Симптомы агрессивного загрузчика: во время перезапуска растёт очередность на диск, а латентность бэкенда ухудшается из‑за конкуренции за I/O. Начните с консервативных значений и постепенно ослабляйте.
use_temp_path и температура записи
По умолчанию Nginx пишет ответы сначала во временный каталог (proxy_temp_path), затем делает rename() в каталог кэша. На локальных POSIX ФС это дёшево, но всё равно двойная запись/перемещение. Если кэш — на отдельном разделе/томе, включите use_temp_path=off, чтобы писать сразу в целевые уровни каталога кэша и исключить лишние движения.
Это снижает количество операций на диске, особенно заметно на медленных или сетевых томах.
Где размещать кэш: ФС, монтирование, лимиты
Рекомендации из практики:
- Выделенный раздел/том под кэш, чтобы
max_sizeне конкурировал с другими данными. - ext4/XFS — предсказуемые и надёжные варианты. Следите за количеством файлов и глубиной каталогов (
levels), чтобы не допускать больших директорий. - relatime или noatime для снижения write‑нагрузки на метаданные.
- inodes: при миллионах мелких файлов следите за исчерпанием inodes, планируйте размер ФС соответствующе.
- Мониторьте через
du/df, наблюдайте латентность диска и ставьте уведомления.
Для развёртывания кэширующего фронта с гибкой конфигурацией удобнее поднимать его на собственном сервере. Если нужен изолированный тариф с быстрым SSD и корневым доступом — рассмотрите облачный VDS.
Базовые паттерны конфигурации
1) Origin-кэш для статики
http {
proxy_cache_path /var/cache/nginx/static levels=1:2 use_temp_path=off
keys_zone=static_cache:128m max_size=200g inactive=30d
loader_files=400 loader_sleep=50ms loader_threshold=300ms
manager_files=400 manager_sleep=200ms manager_threshold=300ms;
map $sent_http_content_type $static_cache_bypass {
default 0;
~*text/html 1; # HTML обычно не кэшируем здесь
}
server {
listen 80;
# ...
location /assets/ {
proxy_cache static_cache;
proxy_cache_bypass $static_cache_bypass;
proxy_cache_valid 200 301 302 30d;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://backend;
}
}
}
Комментарий: длинный TTL на статику безопасен, так как имена обычно «зафиксированы» хешем (fingerprint). inactive=30d при этом позволит автоматически выгружать редко запрашиваемые артефакты. levels=1:2 распределит файлы достаточно ровно для сотен тысяч и миллионов объектов.
2) Микрокэш для API
http {
proxy_cache_path /var/cache/nginx/api levels=1:2 use_temp_path=off
keys_zone=api_cache:32m max_size=2g inactive=30s
loader_files=200 loader_sleep=50ms loader_threshold=200ms
manager_files=200 manager_sleep=200ms manager_threshold=200ms;
server {
listen 80;
location /api/ {
proxy_cache api_cache;
proxy_cache_valid 200 1s; # микрокэш 1 секунда
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on; # защита от thundering herd
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://api_backend;
}
}
}
Комментарий: маленькая keys_zone и скромный max_size тут уместны; ключ — корректный proxy_cache_key и время жизни.
Как посчитать размеры до выката
Шаги оценки:
- Оцените рабочий набор: сколько уникальных URL реально запрашивается за интервал, равный желаемому TTL? Если есть логи — посчитайте по ним уникальные ключи с учётом параметров запроса.
- Оцените средний размер ответа. Умножьте на ожидаемое число записей в кэше — получите ориентир для
max_size. - Добавьте 20–50% запаса на вариативность, заголовки, служебные блоки ФС.
- Рассчитайте
keys_zoneпо формуле 1 МБ ≈ 8k ключей и умножьте на 1.3–2 для запаса. - Выберите
levels, чтобы обеспечить не более 5–10 тыс. файлов в каталоге.
Диагностика: как понять, что всё работает
- Добавьте
$upstream_cache_statusв логи, чтобы видеть HIT/BYPASS/MISS/EXPIRED/UPDATING. - Следите за ошибками «could not allocate node in cache keys zone» и «cache file … has incorrect size».
- Проверяйте фактический рост кэша:
du -sh /var/cache/nginx/staticиdf -h. - Старт/рестарт: если загрузчик слишком агрессивен, увеличьте
loader_sleepи уменьшитеloader_files. - Если диск регулярно забивается и идёт тяжёлая эвикция — пересмотрите
max_sizeиinactive, проверьте рабочий набор.
log_format cache '$remote_addr - $host "$request" $status $body_bytes_sent '
'$upstream_cache_status $request_time $upstream_response_time';
access_log /var/log/nginx/access_cache.log cache;

Типичные ошибки и как их избежать
- Слишком маленькая keys_zone. Ведёт к отказу от кэширования новых объектов. Решение: увеличить до расчётного уровня и перезапустить Nginx.
- Неподходящий levels. Миллионы файлов в одном каталоге — беда для ФС. Решение: спланировать уровни до запуска или мигрировать с чисткой кэша.
- max_size «впритык» к диску. Очистка не успевает, система уходит в 100% usage. Решение: уменьшить
max_sizeлибо расширить том. - inactive короче, чем реальные паттерны запросов. Полезные файлы вымываются. Решение: увеличить
inactiveдля редкого, но критичного контента. - Игнорирование I/O на старте. Перезапуск в часы пик вызывает деградацию. Решение: настроить
loader_*иmanager_*, использовать щадящие значения. - Смешивание кэша и приложений на одном разделе. Всплески кэша выжирают место. Решение: выделить отдельный том.
Оптимизационные штрихи
- Корректная генерация ключей: учитывайте протокол, хост, URI, параметры; исключайте несущественные параметры через
map. - Используйте
proxy_cache_lockиproxy_cache_use_staleдля снижения нагрузки и защиты от «шторма». - Разделяйте зоны для разных классов трафика: мелкие API и крупные медиа не должны конкурировать за
max_size. - Следите за файловыми лимитами и ulimit; кэш — это много файловых дескрипторов.
- Если кэш огромен и «холодный» старт дорогой — рассматривайте ступенчатые рестарты и плавные перезагрузки конфигурации.
Для HTTPS‑трафика убедитесь, что терминатор TLS настроен корректно; при необходимости приобретите надёжные SSL-сертификаты.
Если работаете с защищённой отдачей и сроками годности ссылок, посмотрите материал про secure_link и TTL: управление TTL кэша через Secure Link. А для сегментированного видео и аудио пригодится разбор диапазонов: кэш и Range‑запросы.
Чек-лист перед продом
- Посчитали рабочий набор и размеры: есть план по
keys_zoneиmax_size. - Выбрали
levelsсогласно масштабу. - Решили вопрос с томом/ФС, включили
relatime. - Включили
use_temp_path=offпри отдельном разделе под кэш. - Настроили
loader_*иmanager_*с консервативных значений. - Добавили метки в логах (
$upstream_cache_status) и алерты наdu/df. - Прогонили нагрузочный тест: проверили HIT‑рейты и латентность.
FAQ: коротко о главном
Нужно ли всегда задавать max_size? Да. Без него кэш может неограниченно расти до полного диска. Это опасно.
Что будет, если keys_zone меньше реального набора ключей? Новые записи перестанут индексироваться, кэш станет бесполезным. Увеличьте и перезапустите.
Связь между inactive и заголовками TTL? TTL определяет «свежесть» объекта. inactive удаляет неиспользуемые объекты раньше TTL, чтобы чистить «забытые» данные.
Когда увеличивать loader_files? Когда старт занимает слишком много времени, а диск справляется по IOPS/latency. Увеличивайте дозированно.
Подходят ли одинаковые настройки для статики и API? Обычно нет. Разносите зоны кэша и пресеты отдельно.
Итоги
proxy_cache_path — фундамент кэширования в Nginx. Грамотно рассчитанные keys_zone, max_size и inactive определяют стабильность и эффективность, а аккуратный троттлинг loader_* и manager_* спасает от I/O‑шторма при запуске и в процессе очистки. Планируйте уровни каталогов, отделяйте кэш на собственный том, наблюдайте за поведением в логах и метриках — и кэш будет помогать, а не мешать.


