Новинка Виртуальный VDS сервер в Нидерландах от 390р
Выберите продукт

Nginx proxy_cache_path: разбор keys_zone, max_size, inactive и тонкая настройка

Если вы кэшируете ответы через Nginx, директива proxy_cache_path определяет каталог на диске, глубину levels, объём keys_zone и правила очистки через max_size и inactive. Разбираем тонкую настройку, троттлинг loader/manager, выбор use_temp_path и диагностику с практическими примерами.
Nginx proxy_cache_path: разбор keys_zone, max_size, inactive и тонкая настройка

Когда речь заходит о кэше в 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: inactive 10–60 секунд (агрессивно чистить).
  • Кэш статики с fingerprint-именами: 7–30 дней (редко запрашиваемые файлы выпадут сами).
  • Медиаконтент или архивы: от часов до дней, зависит от закономерностей повторных обращений.

TTL кэша задают заголовки upstream либо директивы типа proxy_cache_valid. inactive дополняет TTL, удаляя то, к чему не было запросов достаточно долго. Эти механизмы работают совместно.

Структура каталогов кэша Nginx с уровнями levels

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.

FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды

Базовые паттерны конфигурации

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 и время жизни.

Как посчитать размеры до выката

Шаги оценки:

  1. Оцените рабочий набор: сколько уникальных URL реально запрашивается за интервал, равный желаемому TTL? Если есть логи — посчитайте по ним уникальные ключи с учётом параметров запроса.
  2. Оцените средний размер ответа. Умножьте на ожидаемое число записей в кэше — получите ориентир для max_size.
  3. Добавьте 20–50% запаса на вариативность, заголовки, служебные блоки ФС.
  4. Рассчитайте keys_zone по формуле 1 МБ ≈ 8k ключей и умножьте на 1.3–2 для запаса.
  5. Выберите 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;

Логи Nginx с upstream_cache_status и график использования диска

Типичные ошибки и как их избежать

  • Слишком маленькая 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‑запросы.

Чек-лист перед продом

  1. Посчитали рабочий набор и размеры: есть план по keys_zone и max_size.
  2. Выбрали levels согласно масштабу.
  3. Решили вопрос с томом/ФС, включили relatime.
  4. Включили use_temp_path=off при отдельном разделе под кэш.
  5. Настроили loader_* и manager_* с консервативных значений.
  6. Добавили метки в логах ($upstream_cache_status) и алерты на du/df.
  7. Прогонили нагрузочный тест: проверили HIT‑рейты и латентность.
FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

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‑шторма при запуске и в процессе очистки. Планируйте уровни каталогов, отделяйте кэш на собственный том, наблюдайте за поведением в логах и метриках — и кэш будет помогать, а не мешать.

Поделиться статьей

Вам будет интересно

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

После одновременной остановки всех узлов Galera обычного запуска MariaDB недостаточно. Сначала найдите сервер с последней транзакц ...
CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

Разберём, почему CoreDNS перезапускается или отвечает SERVFAIL, как обнаружить замкнутую пересылку DNS-запросов, проверить доступн ...
Apache Kafka KRaft на VDS: отдельные controller и broker

Apache Kafka KRaft на VDS: отдельные controller и broker

Соберём новый Kafka-кластер без ZooKeeper на шести Linux VDS: три узла controller образуют отказоустойчивый metadata quorum, а три ...