Кеш в Nginx для динамического сайта: где искать прирост
Кеширование в Nginx может снять часть нагрузки с приложения, но не ускорит сайт автоматически: ошибочный ключ отдаст одному пользователю страницу другого. Разбираем, что измерять до и после, как включать кеш безопасно и где он ломается.

Кеш Nginx способен отдать сохранённый ответ без повторного запроса к приложению — но на динамическом сайте это ускорение легко купить ценой чужой корзины или устаревшего профиля. Универсальных цифр «до и после» нет: результат зависит от доли повторных запросов, времени ответа приложения и правил персонализации. Ниже — схема для Nginx 1.24+ с проксируемым приложением и план измерений, который покажет эффект именно на вашем трафике.
Что именно кеширует Nginx
Речь о proxy_cache: Nginx сохраняет ответ upstream-сервера и использует его повторно для запросов, которые попадают под те же условия кеширования. Это не кеширование PHP-объектов и не ускорение самого приложения. Если каждый запрос уникален или ответ всегда персональный, попаданий в кеш будет мало.
Сначала определите, какие страницы можно безопасно отдавать повторно: например, публичные карточки товаров и категории. Личный кабинет, корзина и страницы с персональными ценами обычно требуют обхода кеша. Решение зависит от того, где приложение выставляет заголовки и как устроена авторизация.
Термин: cache hit — запрос, для которого Nginx нашёл подходящий сохранённый ответ; cache miss — ответа в кеше нет, и запрос уходит к приложению.
Почему «включить кеш на всё» опасно
Кеш должен отличать ответы, которые различаются по содержимому. Если приложение выдаёт разные страницы для пользователей, а ключ кеша этого различия не учитывает, Nginx может повторно отдать один ответ разным посетителям. Обратная ошибка — включить в ключ слишком много параметров: тогда варианты страницы размножаются, и большая часть запросов становится miss.
Ещё один источник сюрпризов — заголовки приложения. Nginx может учитывать Cache-Control и другие заголовки upstream, запрещающие кеширование; поведение задают директивы кеша и их параметры. Не отключайте эту защиту вслепую: сначала выясните, зачем приложение выставило заголовок.
Скорость кеша измеряется не только миллисекундами. Если он отдаёт неверную версию страницы, это не оптимизация, а ошибка показа данных.
Три подхода и их цена
| Подход | Что выигрываете | Чем платите | Где уместен |
|---|---|---|---|
| Не кешировать в Nginx | Ответ всегда формирует приложение по текущим данным | Каждый запрос нагружает приложение | Персональные страницы и ответы, которые нельзя безопасно переиспользовать |
| Кешировать публичные ответы по URL | Просто внедрить и проверить на страницах без персонализации | Нужно учитывать query string, cookies и правила обновления | Публичные каталоги и страницы, одинаковые для посетителей |
| Кешировать с обходом для авторизованных | Публичные запросы разгружают приложение, личные идут к нему напрямую | Нужно надёжно распознавать авторизацию и проверять все варианты ответа | Сайты с публичным контентом и отдельной авторизованной зоной |
Для первого запуска обычно разумнее ограниченный кеш публичных страниц, чем глобальное кеширование всех ответов. Инвалидация кеша — отдельная тема: здесь важно понять, как измерить и безопасно включить повторное использование ответов.
Минимальная конфигурация для проксируемого приложения
Пример ниже рассчитан на Nginx 1.24+ и HTTP-приложение за upstream. Он создаёт зону кеша и включает её в выбранном location. Перед применением адаптируйте адрес upstream и путь к каталогу, проверьте конфигурацию командой nginx -t и сначала разверните изменение на тестовом стенде. Пример не решает автоматически персонализацию: включайте его только для ответов, которые безопасно повторно отдавать.
http {
proxy_cache_path /var/cache/nginx/site
levels=1:2
keys_zone=site_cache:10m
max_size=1g
inactive=60m;
upstream app_backend {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name example.test;
location /public/ {
proxy_pass http://app_backend;
proxy_cache site_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 10s;
add_header X-Cache-Status $upstream_cache_status;
}
}
}
Здесь TTL в 10 секунд — демонстрационное значение, а не рекомендация для любого сайта. Параметр max_size ограничивает размер кеша на диске, а inactive задаёт, как долго неиспользуемые элементы могут оставаться в зоне. Значение X-Cache-Status удобно для диагностики, но не оставляйте диагностический заголовок публичным без необходимости.
Ключ включает схему, метод, host и URI, включая query string. Это снижает риск смешать разные варианты запроса, но может ухудшить hit rate, если в URL есть параметры аналитики. Не убирайте параметры из ключа, пока не доказали, что они не меняют ответ.
Как получить честные цифры до и после
Сравнивайте одинаковые сценарии на одинаковой нагрузке. Иначе изменение трафика, прогрев кеша или состояние базы данных легко принять за эффект Nginx. До включения зафиксируйте исходный результат; после запуска отдельно измерьте холодный кеш и прогретый.
- Выберите страницы. Возьмите конкретные публичные URL и отдельно перечислите авторизованные сценарии, которые не должны попадать в кеш. Проверка: для каждого URL понятно, должен ли он кешироваться.
- Зафиксируйте условия. Запишите версию Nginx, конфигурацию приложения, объём тестового набора URL, длительность прогона и параллельность. Проверка: второй прогон можно повторить с теми же условиями.
- Измерьте базовую линию. Соберите p50 и p95 времени ответа, частоту 5xx и загрузку приложения без кеша. Не смешивайте тестовые и реальные запросы без маркировки. Проверка: показатели сохранены с временным интервалом и описанием нагрузки.
- Включите кеш и проверьте ответы. Сначала убедитесь, что одинаковые публичные запросы дают ожидаемые ответы, а персональные обходят кеш. Заголовок статуса должен показывать miss на первом запросе и hit на повторном, если ответ разрешено кешировать. Проверка: нет чужих данных и неожиданных кешированных ошибок.
- Повторите нагрузочный прогон. С теми же URL и параметрами сравните p50, p95, долю hit, 5xx и нагрузку приложения. Проверка: рядом лежат исходные и новые значения, а не одно среднее число без контекста.
В публикации результатов указывайте условия измерений: окружение, состав запросов, параллельность и прогрев. Без собственных замеров нельзя честно обещать конкретное ускорение. Полезный результат может быть не только в более низком p95, но и в уменьшении нагрузки на приложение при сохранении приемлемой свежести страниц.
Что ломается первым
В кеше оказываются персональные ответы
Симптом — пользователь видит не своё содержимое или состояние страницы не совпадает с аккаунтом. Немедленно отключите кеш на затронутом маршруте, проверьте ключ и заголовки приложения, очистите сохранённые ответы и повторите тест с разными сессиями. Не считайте проверку одного анонимного браузера достаточной.
Hit rate низкий, а нагрузка не падает
Проверьте, не меняются ли URL, query string, cookies и заголовки между запросами и разрешает ли приложение кешировать ответ. Высокая вариативность ключа может создавать множество отдельных записей. Сокращать ключ можно только после проверки, что исключённые параметры не меняют содержимое ответа.
После обновления страницы показывают старые данные
Проверьте заданный TTL и правила приложения для Cache-Control. Короткий TTL ограничивает период устаревания, но не отменяет необходимость продумать обновление данных после публикации или изменения цены. Если свежесть критична, не задавайте срок жизни по привычке — согласуйте его с владельцем данных.
Ответы 5xx тоже сохраняются или приложение продолжает перегружаться
Посмотрите, какие коды ответа кешируются, и сопоставьте их с конфигурацией и логами. Затем проверьте, не проходят ли запросы мимо кеша из-за различий в ключах или запретов upstream. Менять кеширование ошибок и заголовки приложения без проверки опасно: можно продлить сбой или замаскировать его.
Где подход ломается
Кеш на уровне Nginx не подходит как универсальный ответ для страниц, чьё содержимое меняется от пользователя, сессии, географии или актуального состояния транзакции. Он также не заменяет очередь, оптимизацию медленного SQL-запроса или кеширование внутри приложения: если проблема возникает до формирования HTTP-ответа, выигрыш может быть ограничен.
Для прода следите как минимум за долей hit/miss, p95 ответа, 5xx и нагрузкой на upstream. Проверяйте не только обычный трафик, но и редкие варианты: пустой кеш после перезапуска, изменение query-параметров, вход и выход из аккаунта, обновление контента. Если эти сценарии не покрыты, оценка «после» неполная.
Что делать дальше
Начните с одного публичного маршрута и короткого пилота: запишите базовые метрики, включите кеш только там, проверьте повторные запросы и сравните результаты на том же профиле нагрузки. Затем добавьте автоматизированную проверку, что авторизованные ответы не получают статус cache hit. Только после этого расширяйте список URL и согласуйте допустимую задержку обновления с владельцами контента.
Инфографика для маркетплейса: Три главных преимущества товара короткими фразами, выноски в безопасной зоне превью, точный размер площадки.
Спросить за 60 ₽Источники: NGINX documentation: ngx_http_proxy_module, NGINX documentation: ngx_http_upstream_module
Частые вопросы
Насколько быстрее станет сайт после включения proxy_cache?
Можно ли кешировать весь сайт?
Как понять, что Nginx отдал ответ из кеша?
Что делать, если после включения кеша показываются старые данные?
Подойдёт ли эта конфигурация, если приложение работает через PHP-FPM?
Можно ли получить такие же цифры на любом сервере?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.