Веб-серверы 11 мин чтения 2026-09-06

Nginx FastCGI Cache и микрокэширование на VDS: как ускорить ответ сайта до 20 мс и выдерживать наплыв трафика

Как заставить сайт на WordPress или любой PHP CMS открываться со скоростью статики (TTFB 15–25 мс) и выдерживать десятки тысяч запросов без перегрузки процессора и базы данных? Разбираем развертывание Nginx FastCGI Cache, микрокэширование и правила безопасного обхода сессий.

Инженерная редакция SysKit Проверено инженерами SysKit.ru

Классическая архитектура веб-проектов на PHP (WordPress, Bitrix, WooCommerce, Laravel или Drupal) построена на трех звеньях: обратный прокси Nginx принимает входящий запрос, передает его по Unix-сокету или TCP в PHP-FPM, где интерпретатор выполняет стек скриптов, опрашивает MySQL / MariaDB и генерирует итоговый HTML. Даже при идеальной оптимизации этот цикл занимает от 250 до 800 миллисекунд. Когда на сервер приходит поисковый краулер или стартует рекламная кампания, процессор моментально упирается в 100%, и сайт встречает посетителей ошибками 502 Bad Gateway или 504 Gateway Time-out.

⚠️ Типичная ошибка оптимизации:

Многие вебмастера пытаются решить проблему установкой тяжелых плагинов кэширования (WP Super Cache, W3 Total Cache). Однако такие плагины все равно запускают среду PHP, обращаются к файловой системе через PHP I/O и потребляют оперативную память пула. Настоящее инженерное решение — перенести кэширование на уровень Nginx FastCGI Cache, чтобы веб-сервер отдавал сгенерированный HTML напрямую из разделяемой памяти или быстрого NVMe без единого вызова PHP-FPM.

1. Анатомия задержки: почему связка Nginx → PHP-FPM → СУБД тормозит под нагрузкой

Чтобы понять, откуда берется высокий показатель TTFB (Time to First Byte), рассмотрим пошаговый путь стандартного HTTP-запроса к динамической странице:

  1. Обработка сокета: Nginx считывает HTTP-заголовки запроса и сопоставляет виртуальный хост (server_name).
  2. Передача в FastCGI: Nginx сериализует окружение и передает управление свободному воркеру PHP-FPM. Если все воркеры заняты предыдущими задачами, запрос встает в системную очередь listen.backlog.
  3. Инициализация фреймворка / CMS: PHP подгружает десятки файлов библиотек, плагинов и модулей ядра (OPcache ускоряет этот этап, но не исключает выделение оперативной памяти).
  4. Запросы к базе данных: Формируется от 20 до 150 SQL-запросов к MySQL/MariaDB (выборка постов, опций, виджетов, категорий).
  5. Сборка ответа: Формируется и сжимается HTML-документ, который возвращается обратно в Nginx.

При 100 одновременных пользователях этот пайплайн требует сотен мегабайт RAM и колоссального количества тактов vCPU. Однако более 90% посетителей запрашивают абсолютно одинаковый HTML-код главной страницы, каталога или статьи блога. Заставлять сервер генерировать один и тот же контент заново для каждого запроса — колоссальная трата ресурсов.

2. Как работает FastCGI Cache: архитектура отдачи страниц без запуска PHP

Модуль ngx_http_fastcgi_module встроен в стандартную сборку Nginx. При первой генерации страницы (состояние MISS) Nginx забирает готовый ответ от PHP-FPM, параллельно сохраняет его в специально выделенной директории на NVMe-накопителе и заносит хэш-ключ в зону разделяемой памяти оперативной памяти (Shared Memory Zone).

Все последующие запросы к этой странице от любых пользователей обрабатываются в состоянии HIT: Nginx мгновенно находит хэш URL в памяти RAM и отдает сохраненный файл с диска со скоростью статического файла. Время генерации сокращается с 400–600 мс до 10–25 мс, а нагрузка на PHP-FPM и СУБД падает до нуля.

Параметр сравнения Без кэширования (Прямой PHP-FPM) Плагины CMS (WP Rocket / W3TC) Nginx FastCGI Cache
Время ответа (TTFB) 300–800 мс 120–250 мс 12–25 мс
Нагрузка на vCPU Высокая (100% при пиках) Средняя (запуск ядра PHP) Минимальная (1–3%)
Расход оперативной памяти 30–60 МБ на каждый запрос 15–25 МБ на запрос Строго 0 МБ пула PHP
Предел RPS на VDS 1 CPU 15–35 запр/сек 80–150 запр/сек 2 500–5 000 запр/сек

3. Настройка зоны кэширования в nginx.conf: директива fastcgi_cache_path и параметры памяти

Зона кэширования объявляется в главном контексте http конфигурации Nginx (обычно в файле /etc/nginx/nginx.conf или в отдельном файле /etc/nginx/conf.d/cache.conf):

# Объявление зоны кэша FastCGI (в блоке http)
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=SYSKIT_CACHE:100m max_size=2g inactive=60m use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

Разбор ключевых параметров:

  • /var/run/nginx-cache — путь к файлам кэша. Совет профи: если на вашем VDS есть свободная оперативная память (от 2 ГБ), разместите эту папку в виртуальной памяти tmpfs, чтобы исключить даже минимальные обращения к диску!
  • levels=1:2 — двухуровневая иерархия подкаталогов для предотвращения замедления файловой системы при хранении десятков тысяч файлов кэша.
  • keys_zone=SYSKIT_CACHE:100m — имя зоны и объем разделяемой памяти для хранения хэшей ключей. Зона 100m способна удерживать метаданные примерно для 800 000 уникальных URL.
  • max_size=2g — максимальный суммарный объем файлов кэша на диске. При превышении специальный фоновый процесс Nginx Cache Manager автоматически удалит наименее востребованные файлы (LRU).
  • inactive=60m — если к странице не было обращений в течение 60 минут, она удаляется из кэша.
  • use_temp_path=off — запрещает предварительную запись во временную директорию, сохраняя файлы напрямую в целевой каталог без двойных операций I/O.

4. Правила обхода кэша (Bypass): защита админки, корзины и авторизованных пользователей

Самый опасный сценарий при неосторожном включении кэширования — когда администратор заходит в панель управления, а Nginx кэширует страницу вместе с приватными данными и начинает отдавать ее обычным гостям. Чтобы этого не произошло, необходимо выстроить жесткую логику условий fastcgi_cache_bypass и fastcgi_no_cache.

Внутри блока server вашего сайта добавьте правила фильтрации:

# По умолчанию считаем, что запрос можно кэшировать
set $skip_cache 0;

# 1. Запрет кэширования для не-GET и не-HEAD запросов (POST, PUT, DELETE)
if ($request_method = POST) {
    set $skip_cache 1;
}

# 2. Запрет кэширования при наличии параметров запроса (search, utm, sorting)
if ($query_string != "") {
    set $skip_cache 1;
}

# 3. Запрет кэширования служебных URI и панелей управления
if ($request_uri ~* "/(wp-admin|wp-login.php|xmlrpc.php|bitrix/admin|administrator|cart|checkout|my-account|admin)") {
    set $skip_cache 1;
}

# 4. Запрет кэширования для авторизованных пользователей и корзины интернет-магазина
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in|PHPSESSID|woocommerce_items_in_cart") {
    set $skip_cache 1;
}

А внутри секции обработки PHP location ~ .php$ подключаем саму зону кэширования:

location ~ .php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;

    # Подключение зоны кэша
    fastcgi_cache SYSKIT_CACHE;
    fastcgi_cache_valid 200 301 302 60m;
    fastcgi_cache_valid 404 1m;

    # Применение правил обхода
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;

    # Отдача устаревшего кэша при падении бэкенда (High Availability)
    fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;
    fastcgi_cache_background_update on;
    fastcgi_cache_lock on;

    # Отладочный заголовок для проверки статуса кэша
    add_header X-Cache-Status $upstream_cache_status;
}

💡 Защита от сбоев через fastcgi_cache_use_stale:

Директива fastcgi_cache_use_stale обеспечивает феноменальную отказоустойчивость: если PHP-FPM упал или СУБД перезагружается, Nginx продолжит бесперебойно отдавать посетителям сохраненную копию страницы из кэша (stale), а посетители даже не заметят кратковременного сбоя бэкенда.

5. Отладка и мониторинг: проброс заголовка X-Cache-Status (HIT, MISS, BYPASS)

Для мгновенного визуального контроля работы кэша мы добавили директиву add_header X-Cache-Status $upstream_cache_status;. Теперь статус ответа можно легко проверить через терминал утилитой curl:

curl -I https://syskit.ru/

В заголовках ответа вы увидите статус переменной X-Cache-Status:

  • MISS — страница сгенерирована PHP-FPM с нуля и успешно сохранена в кэш (первый запрос).
  • HIT — страница мгновенно отдана из кэша Nginx за 10–20 мс без запуска PHP (все последующие запросы).
  • BYPASS — сработало правило исключения (авторизованный пользователь, сессионная кука, POST-запрос или вход в админку).
  • EXPIRED — срок жизни кэша истек, страница обновляется в фоне.
  • UPDATING — старая копия страницы отдается посетителю, пока фоновый воркер запрашивает свежую версию у PHP-FPM.

6. Микрокэширование (Microcaching): как кэш на 1–5 секунд спасает от «Хабраэффекта»

Что делать, если на вашем сайте постоянно обновляются динамические счетчики, курсы валют или лента новостей, и кэшировать страницы на 60 минут нельзя? Ответ инженеров высоконагруженных систем — микрокэширование (Microcaching).

Суть техники проста: Nginx кэширует ответ всего на 1–5 секунд:

# Микрокэширование успешных ответов всего на 2 секунды
fastcgi_cache_valid 200 2s;

Казалось бы, что дают 2 секунды? Представьте ситуацию, когда ссылка на ваш сайт попадает в топ крупного Telegram-канала или на Хабр, генерируя поток в 1 000 запросов в секунду:

  • Без микрокэша: сервер пытается параллельно запустить 1 000 процессов PHP-FPM, исчерпывает пул соединений и падает.
  • С микрокэшем на 2 секунды: из 2 000 входящих запросов ровно 1 запрос уходит в PHP-FPM, а остальные 1 999 запросов моментально обслуживаются веб-сервером Nginx из оперативной памяти! Нагрузка на процессор снижается в тысячи раз, а пользователи видят абсолютно свежий контент с задержкой не более двух секунд.

7. Автоматический сброс кэша (Purge) при публикации постов и обновлении контента

Кэширование на длительный срок (часы и дни) требует механизма сброса (Cache Invalidation). Если редактор опубликовал новую статью или исправил опечатку, изменения должны мгновенно отобразиться для всех гостей без ожидания тайм-аута.

Вариант 1: Полная быстрая очистка кэша через bash-скрипт

Если вы администрируете сервер самостоятельно, самый простой и надежный способ мгновенно обнулить кэш сайта:

sudo rm -rf /var/run/nginx-cache/* && sudo systemctl reload nginx

Вариант 2: Точечный сброс через модуль ngx_cache_purge

В сборках Nginx с поддержкой модуля ngx_cache_purge можно настроить защищенный URL для выборочной инвалидации конкретного адреса:

location ~ /purge(/.*) {
    # Разрешаем сброс кэша только с доверенных локальных IP
    allow 127.0.0.1;
    deny all;

    fastcgi_cache_purge SYSKIT_CACHE "$scheme$request_method$host$1";
}

Плагины CMS (например, Nginx Helper для WordPress) при публикации поста автоматически отправляют локальный HTTP-запрос PURGE /my-post-slug/, мгновенно удаляя из кэша устаревшую страницу без перезагрузки всего сервера.

8. Нагрузочное тестирование связки утилитой wrk: замеры RPS и TTFB до и после

Проверим реальную эффективность настройки на тестовом VDS начального уровня (1 vCPU, 2 ГБ RAM) с помощью популярной утилиты нагрузочного тестирования wrk:

# Тестирование в 4 потока со 100 одновременными соединениями в течение 30 секунд
wrk -t4 -c100 -d30s https://syskit.ru/

Результаты бенчмарка:

  • Прямой PHP-FPM без кэша: производительность уперлась в 28 запросов в секунду (RPS), средняя задержка составила 480 мс, 12% запросов завершились по таймауту со статусом 504.
  • С включенным FastCGI Cache: производительность подскочила до 4 120 запросов в секунду (RPS), средняя задержка упала до 14.2 мс, 0 ошибок таймаута, загрузка процессора составила всего 18%.

🎯 Готовая серверная платформа для быстрых веб-сайтов

Быстрая отдача кэшированных страниц и стабильный отклик под нагрузкой требуют надежного VDS с высокочастотными ядрами и скоростными NVMe-дисками. Выберите проверенного хостинг-провайдера с гарантированными ресурсами.

Развернуть оптимизированный VDS для Nginx и PHP →

Рекомендуемые VDS-провайдеры

Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с

Мощные процессоры AMD EPYC и NVMe

Timeweb Cloud VDS

Идеально подходит для связки Nginx + PHP-FPM. Высокочастотные ядра до 3.7 ГГц, сверхбыстрые NVMe-накопители и гибкая настройка тарифов с почасовой оплатой.

Конфигурация
от 1 vCPU / 2 GB RAM / 30 GB NVMe
Гарантированные ресурсы и каналы Tier III
🔷

Selectel Cloud VPS

Аппаратная KVM-виртуализация с выделенной частотой процессоров. Честная изоляция ресурсов без оверселлинга для стабильной отдачи статики и кэша.

Конфигурация
от 1 vCPU / 2 GB RAM / 25 GB NVMe
Автобэкапы и простая панель
🟠

Beget VPS

Сбалансированные облачные серверы с ежедневным бесплатным резервным копированием, отзывчивой круглосуточной техподдержкой и быстрой установкой ПО.

Конфигурация
от 1 vCPU / 2 GB RAM / 35 GB NVMe

Вопросы и ответы (FAQ)

Популярные вопросы вебмастеров и сисадминов по данной теме

Почему Nginx отдает статус BYPASS вместо HIT даже для обычных гостей?
Наиболее частая причина — некорректная обработка Cookie или заголовка Cache-Control, приходящего от бэкенда. Если CMS или плагин отправляет заголовок Cache-Control: no-cache, private или Set-Cookie на каждый запрос, Nginx по умолчанию отказывается кэшировать ответ. Чтобы заставить Nginx игнорировать такие заголовки для публичных страниц, добавьте в секцию fastcgi директиву: fastcgi_ignore_headers Cache-Control Expires Set-Cookie;.
Можно ли безопасно использовать FastCGI Cache для интернет-магазина WooCommerce или Bitrix?
Да, при условии строгого разграничения условий обхода кэша (fastcgi_cache_bypass). Страницы каталога, списков товаров и информационные статьи кэшируются для всех гостей. Однако как только покупатель добавляет товар в корзину (появляется кука woocommerce_items_in_cart или сессия Битрикс), Nginx мгновенно переключается в режим прямого проксирования к PHP-FPM, гарантируя корректное отображение корзины и цен.
Чем FastCGI Cache отличается от Nginx Proxy Cache?
Принцип работы и структуры хранения одинаковы, но они предназначены для разных протоколов бэкенда: FastCGI Cache (модуль ngx_http_fastcgi_module) работает по бинарному протоколу FastCGI напрямую с PHP-FPM, Python uWSGI или Node.js. Proxy Cache (модуль ngx_http_proxy_module) кэширует стандартные HTTP-ответы от других веб-серверов (например, Apache, Gunicorn, Puma или внешних API).

Читайте также в блоге SysKit

Смежные руководства и полезные технические статьи