Прогревать кеш большого каталога на Битриксе целиком — плохая идея: обход сотен тысяч страниц займёт десятки часов и сам положит сервер. Работает другое: после тяжёлого обновления базы сбросить только нужный кеш, отобрать из sitemap страницы, которые реально важны (разделы каталога и SEO-страницы), и прогреть их медленно, с паузами, по расписанию после импорта. В этом кейсе так из 7329 URL осталось 318, а ответ сервера упал с 2524 до 190 мс.
Что случилось
Время генерации страницы без попадания в кеш достигало 2524 мс. Старт PHP-процесса, инициализация сессии и десятки запросов к БД для сборки фильтра — всё это на каждый промах кеша.
Пока кеш тёплый, это незаметно. Но после ночного импорта цен кеш сбрасывался, и в этот момент приходили краулеры. Каждый их запрос — те самые 2.5 секунды работы воркера. Свободные воркеры заканчивались мгновенно, CPU уходил в 100%. Полный прогрев каталога штатными средствами занял бы десятки часов и положил бы сервис не хуже ботов.
Почему холодный кеш так дорого стоит
Страница каталога на Битриксе с умным фильтром — это много работы: ядро, сессия, запросы к инфоблокам, свойства для фильтра, SEO-данные. Кеш компонентов прячет эту цену, но только пока он есть. Любое массовое обновление (импорт из 1С, пересчёт цен, правки свойств) инвалидирует теги, и следующий посетитель платит полную цену.
Проблема не в том, что кеш сбрасывается, — так и должно быть. Проблема в том, кто первым приходит за холодной страницей. Если это ваш собственный скрипт в 11:30 утра — хорошо. Если сотня краулеров одновременно — плохо.
Шаг 1. Сбросить именно то, что устарело
Первым делом — PHP-скрипт, который чистит таблицы SEO-модуля и сбрасывает его тегированный кеш. Не весь кеш сайта, а то, что относится к SEO-данным:
<?php
define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS", true);
$_SERVER["DOCUMENT_ROOT"] = __DIR__;
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
// TODO: замените на свой модуль и его тег кеша
if (\Bitrix\Main\Loader::includeModule('seo.module')) {
\Seo\Module\Models\CacheTable::clearCache();
$GLOBALS['CACHE_MANAGER']->ClearByTag('seo_module');
echo "Cache cleared.\n";
}Сброс по тегу (ClearByTag) — штатный механизм Битрикса: он инвалидирует только записи, помеченные этим тегом, и не трогает остальной кеш.
Шаг 2. Отобрать, что греть
Полный sitemap каталога — 7329 URL. Греть все — те самые десятки часов. Но посетители и поисковики приходят в основном на разделы каталога и SEO-страницы фильтра, а не на каждую карточку.
Bash-скрипт собирает именно их: SEO-страницы из отдельного sitemap и разделы каталога — из sitemap инфоблоков, отрезая от URL товара последний сегмент и убирая дубли. На выходе — 318 целевых адресов.
Шаг 3. Греть медленно
Прогрев не должен сам стать нагрузкой. wget --spider запрашивает страницы, не сохраняя их, а --wait=1 --random-wait делает паузы между запросами — сервер спокойно обслуживает реальных посетителей параллельно.
#!/bin/bash
# TODO: замените домен и путь к сайту
SITE="https://client-site.com"
DOCROOT="/var/www/client/data/www/client-site.com"
php -f $DOCROOT/clear_seo.php
SEO_URLS=$(curl -s $SITE/seo-sitemap/sitemap-1.xml | grep -oP '(?<=<loc>).*?(?=</loc>)')
IBLOCK_MAPS=$(curl -s $SITE/sitemap.xml | grep -oP '(?<=<loc>).*?(?=</loc>)' | grep 'sitemap-iblock')
SECTION_URLS=$(echo "$IBLOCK_MAPS" | xargs -I {} curl -s {} | grep -oP '(?<=<loc>).*?(?=</loc>)' | sed 's#[^/]*/*$##' | sort | uniq)
ALL_URLS=$(echo -e "$SEO_URLS\n$SECTION_URLS" | grep "http" | sort | uniq)
echo "$ALL_URLS" > /tmp/warmup_urls.txt
wget -q --spider -i /tmp/warmup_urls.txt --wait=1 --random-wait
rm -f /tmp/warmup_urls.txt318 адресов с паузой около секунды — это минуты, а не часы.
Шаг 4. Запускать в правильный момент
Прогрев имеет смысл только после того, как данные перестали меняться. Поэтому cron стоит на окно, когда импорт цен уже закончился, а база свободна:
30 11 * * * /var/www/client/data/www/client-site.com/safe_warmup.shЕсли импорт иногда задерживается, надёжнее запускать прогрев не по часам, а последним шагом самого импорта — тогда он никогда не начнётся раньше времени.
Результат
- Время ответа снизилось до 190 мс
- Пики нагрузки на CPU полностью устранены
- SEO-метатеги на 100% актуальны для краулеров
- Рутинный ручной сброс кеша больше не нужен
Как проверить, что прогрев работает
Замерьте время до первого байта до и после прогрева на одной и той же странице:
# TODO: подставьте адрес раздела каталога
curl -s -o /dev/null -w "TTFB: %{time_starttransfer}s\n" https://client-site.com/catalog/section/Холодная страница даст секунды, прогретая — доли секунды. Если после прогрева время не изменилось, значит, кеш сбрасывается снова (например, следующим этапом импорта) или страница вообще не кешируется — проверьте настройки кеширования компонентов.
FAQ
Как прогреть кеш Битрикса после импорта?
Сбросить только устаревший кеш по тегам, собрать из sitemap важные страницы (разделы каталога, SEO-страницы) и запросить их с паузами через wget --spider или curl. Запускать после окончания импорта.
Нужно ли прогревать все страницы каталога? Нет. Полный обход большого каталога занимает часы и сам создаёт нагрузку. Достаточно разделов и страниц, на которые реально приходят посетители и поисковики; карточки товаров прогреются естественным трафиком.
Как не перегрузить сервер прогревом?
Делать паузы между запросами (--wait=1 --random-wait), запускать в окно минимальной нагрузки и греть ограниченный список адресов, а не весь sitemap.
Почему страницы на Битриксе медленные после обновления цен? Импорт инвалидирует кеш компонентов, и первый посетитель получает полную сборку страницы. Прогрев сразу после импорта убирает эту задержку.