Битрикс под нагрузкой: что ломается первым и как это найти
Рассылка ушла, трафик вырос, и через несколько минут сайт на «1С-Битрикс» отдаёт 502, хотя процессор не загружен. Разбираем, в каком порядке отказывают кеш, инфоблоки, агенты, php-fpm и MySQL и что проверить.

Типичный сценарий: маркетинг запускает рассылку, на сайт за считаные минуты приходит заметно больше людей, чем обычно, и nginx начинает отвечать 502. Процессор при этом загружен не на сто процентов. Дело не в нехватке «мощности»: каждый запрос стал держать воркер php-fpm дольше, чем закладывали, и воркеры закончились. Ниже разобран порядок, в котором у «1С-Битрикс» отказывают кеш, инфоблоки, агенты, php-fpm и MySQL.
Как выглядит отказ изнутри
Материал про «1С-Битрикс: Управление сайтом» (ядро D7, инфоблоки 2.0), PHP 8.x, MySQL 8.0 или MariaDB 10.x и связку nginx с php-fpm. Битрикс24 не затрагиваем. Замеров на вашем железе у нас нет, поэтому вместо чужих цифр ниже дан способ снять свои. Выбор между memcached и Redis и сама инвалидация кеша — отдельные темы, здесь только упоминаем.
Запрос проходит три очереди: nginx принимает соединение, php-fpm отдаёт его свободному воркеру, воркер идёт в MySQL и файловую систему. Если любая из них тормозит, воркер остаётся занятым. Когда свободные кончились, новые запросы стоят в очереди php-fpm, а nginx по таймауту отвечает 502 или 504. В логе php-fpm это строка «server reached pm.max_children setting». Это симптом, а не причина: воркеров мало потому, что что-то их держит.
Нагрузка ломает сайт не числом запросов, а тем, что каждый из них держит воркер дольше, чем вы закладывали.
Узкие места в порядке отказа
Порядок типичный, но не гарантированный. У магазина с большим каталогом первым сдаётся фильтр, у новостного сайта кеш.
1. Кеш: холодный старт и массовая инвалидация
Компонентный кеш по умолчанию лежит в файлах: /bitrix/cache/ и /bitrix/managed_cache/. Пока кеш тёплый, страница почти не трогает базу. Как только он сброшен, сотни параллельных запросов находят его пустым, и каждый идёт собирать данные в MySQL одновременно с остальными.
Сброс не всегда ручной. Управляемый кеш сбрасывается по тегам, и у компонентов каталога один из тегов привязан к инфоблоку. Импорт из 1С или массовая правка элементов сбрасывает кеш всех компонентов этого инфоблока, и так при каждом обмене по расписанию. Проверьте, совпадают ли всплески нагрузки по времени с обменом. Отдельно посмотрите параметр «Учитывать права доступа» (CACHE_GROUPS): у большинства компонентов он размножает кеш на каждую комбинацию групп пользователей.
Лавинная пересборка кеша (cache stampede): ситуация, когда кеш истёк, а пересобирать его бросаются все запросы сразу, вместо одного. Тегированный кеш: кеш, привязанный к меткам, например к номеру инфоблока, и сбрасываемый целиком по метке.
2. Страницы, которые в кеш не попадают
Фильтры, сортировки, пагинация и поиск. Боты перебирают комбинации вроде ?sort=..., значений фильтра и PAGEN_1. Каждая комбинация даёт свой ключ кеша, то есть промах и запрос в базу. Заодно растёт каталог кеша: можно упереться в число inode, а не в место на диске.
Что делать: закрыть лишние параметры в robots.txt (от недобросовестных ботов это не защита), ограничить частоту запросов в nginx директивой limit_req_zone, отдавать 404 на несуществующие комбинации, ограничить глубину пагинации. Композитный сайт здесь не спасает: каждый уникальный URL в нём тоже отдельная запись.
3. Инфоблоки: свойства и фильтр
В инфоблоках 2.0 одиночные свойства лежат в одной таблице на инфоблок, множественные в другой. Фильтр по нескольким свойствам превращается в запрос с несколькими JOIN. Для умного фильтра есть фасетный индекс: проверьте, включён ли он в настройках модуля инфоблоков и перестраивался ли после изменения набора свойств. Отдельный источник запросов — search.title: поиск с подсказками стучится в базу при каждом нажатии клавиши.
4. Агенты и почтовые события на хите
По умолчанию агенты запускаются по обращениям посетителей. Тяжёлый агент (пересчёт, обмен, очистка) выполняется внутри запроса обычного пользователя и держит его воркер. Это выглядит как случайные долгие ответы на ровном месте. Решение описано в документации Битрикса как перенос агентов на cron. Схема такая (проверьте детали и сопутствующие настройки главного модуля для своей версии):
// Фрагмент для /bitrix/php_interface/dbconn.php (добавьте в конец файла)
if (!(defined('CHK_EVENT') && CHK_EVENT === true)) {
define('BX_CRONTAB_SUPPORT', true);
}# crontab пользователя сайта: агенты и почтовые события раз в минуту
# замените пути на свои
* * * * * /usr/bin/php -f /home/bitrix/www/bitrix/modules/main/tools/cron_events.php5. Сессии, статистика, корзины
- Сессии. При стандартном файловом обработчике PHP запрос, открывший сессию, держит её блокировку до конца. Параллельные ajax-запросы одного пользователя выстраиваются в очередь. В новых версиях ядра есть способы это смягчить, сверьтесь с документацией своей редакции.
- Модуль статистики пишет в базу на каждый хит. На нагруженном сайте его обычно отключают и заменяют внешней аналитикой.
- Корзины. Анонимные посетители и боты создают записи покупателей и корзин. Убедитесь, что агент очистки старых корзин реально выполняется.
6. php-fpm и MySQL: два лимита, которые надо согласовать
Число воркеров ограничено памятью: свободная RAM под PHP делится на средний RSS воркера. Измерьте его на своём сайте командой ps -eo rss,cmd --sort=-rss | grep '[p]hp-fpm' | head, значение в килобайтах. Если поднять pm.max_children выше возможностей базы, вместо 502 получите ошибку MySQL «SQLSTATE[HY000] [1040] Too many connections». Сумма воркеров по всем веб-серверам должна быть меньше max_connections с запасом на cron, обмен с 1С и администраторов.
| Узкое место | Как проявляется | Как проверить | Первое действие |
|---|---|---|---|
| Холодный кеш | Всплеск нагрузки после обмена или сброса | Совпадение времени всплесков с обменом с 1С | Развести обмен и пик, не сбрасывать кеш в рабочие часы |
| Уникальные URL от ботов | Кеш не помогает, растёт каталог кеша | Топ URL с sort, PAGEN_ и фильтром в access-логе | limit_req_zone, закрыть лишние параметры |
| Фильтр по свойствам | Долгие запросы с JOIN к таблицам свойств | Медленный лог MySQL | Фасетный индекс, его пересборка |
| Агенты на хите | Случайные долгие ответы | slowlog php-fpm, список агентов в админке | Перенос на cron |
| Сессии и статистика | Очередь запросов одного пользователя, много записи в БД | Статус php-fpm, нагрузка на запись в MySQL | Отключить статистику, вынести сессии |
| Лимиты php-fpm и MySQL | 502, 504, ошибка 1040 | Журнал php-fpm, Max_used_connections | Согласовать max_children и max_connections |
Что и как мерить
Готовых цифр «до и после» для Битрикса не бывает: они зависят от каталога, модулей и железа. Придумывать их нельзя, поэтому снимайте свои:
- Поднимите копию сайта с копией базы на стенде с тем же железом, что в проде. Иначе цифры бессмысленны.
- Возьмите нагрузочный инструмент (k6, wrk или Apache JMeter) и ступенчато увеличивайте параллельность на реальных сценариях: главная, листинг с фильтром, карточка, добавление в корзину.
- На каждой ступени записывайте p95 времени ответа, очередь и счётчик «max children reached» со страницы статуса php-fpm, пик соединений MySQL и число записей в медленном логе.
- Повторите тест с пустым кешем. Разница между двумя прогонами и есть цена холодного старта.
Ступень, на которой p95 растёт быстрее трафика, и есть ваш потолок. Смотрите, что в этот момент упёрлось. Диагностика MySQL 8.0 или MariaDB 10.x:
-- Пик занятых соединений с момента запуска сервера и текущий лимит
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
SHOW GLOBAL VARIABLES LIKE 'max_connections';
-- Что выполняется прямо сейчас и сколько секунд
SHOW FULL PROCESSLIST;
-- Медленный лог без перезапуска (нужны права администратора).
-- Порог действует для новых соединений.
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;Пул php-fpm для PHP 8.x. Числа условные, это не рекомендация:
; max_children считайте от памяти: свободная RAM под PHP / средний RSS воркера.
pm = dynamic
pm.max_children = 20
pm.start_servers = 8
pm.min_spare_servers = 4
pm.max_spare_servers = 12
pm.max_requests = 500
; Страницу статуса в nginx отдавайте только с localhost или из внутренней сети.
pm.status_path = /fpm-status
; Трассировка запросов, которые идут дольше 5 секунд.
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/bitrix-slow.logГде подход ломается
- Композитный сайт не снимает нагрузку с авторизованных пользователей, корзины и оформления заказа. Динамические области всё равно идут отдельными запросами.
- Кеш в memcached или Redis быстрее файлового, но после рестарта он пуст, и холодный старт случается сразу у всего сайта. При нехватке памяти ключи вытесняются, и вы получаете неявный частичный сброс.
- Несколько веб-серверов: файловый кеш у каждого свой, сброс на одном не доходит до остальных. Агенты по cron должны выполняться на одном узле, иначе они задвоятся.
- Лимиты в nginx против ботов задевают и поисковых роботов, и реальных пользователей за общим NAT. Сначала посмотрите access-лог, потом включайте.
Что делать дальше
Сегодня включите медленный лог MySQL и страницу статуса php-fpm и дайте им собирать данные неделю. По логу выберите три запроса с наибольшим суммарным временем и сопоставьте их с компонентами на страницах. Затем по очереди: агенты на cron, ограничение ботов, проверка фасетного индекса. В проде следите за p95, очередью php-fpm и долей промахов кеша. Детали настроек для вашей редакции сверяйте в документации 1С-Битрикс.
Агент-продажник: Скрипты B2B-продаж, обработка возражений по BANT и SPIN.
Спросить за 20 ₽Источники: Документация 1С-Битрикс для разработчиков, PHP Manual: конфигурация FPM
Частые вопросы
У меня другая версия Битрикса или PHP. Это применимо?
Я перенёс агенты на cron, и они перестали выполняться. Что проверить?
Сколько воркеров php-fpm ставить?
Хватит ли включить композитный сайт, чтобы пережить пик?
Какие подводные камни при переносе кеша в memcached или Redis?
Можно ли очищать кеш на проде в рабочее время?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.