BX
BX Pulse
Мониторинг сайтов 1С-Битрикс
← Все статьи
Bitrix 12 августа 2026 · 6 мин чтения

Файловые сессии валят Битрикс в пик при спокойном процессоре

Как отличить очередь на блокировке файла сессии от нехватки CPU и когда переносить сессии Битрикса в Redis отдельно от кеша.

2 просмотров

В пик акции сайт на Битриксе отдаёт 504, PHP-FPM весь в Running, а CPU и память ещё спокойные. Админ уже смотрит MySQL и железо — хотя воркеры часто стоят не на расчёте, а на блокировке файла сессии одного пользователя с кучей параллельных AJAX.

Ниже — как отличить «нет CPU» от «воркеры заняты file lock», что проверить в PHP и bitrix/.settings.php, зачем Redis (или ранний session_write_close) и почему сессии нельзя держать в той же Redis-БД, что и кеш.

Почему FPM красный, а процессор зелёный

Схема: очередь FPM на блокировке файла сессии при зелёном CPU

Дефолт PHP: session.save_handler = files, файлы вида sess_<id> в session.save_path (часто /tmp). При session_start() обработчик берёт exclusive lock на файл сессии и держит его до session_write_close() или конца скрипта — с одной сессией в момент времени работает только один скрипт.

Параллельные запросы с одним session ID — вкладки, AJAX каталога, корзины, виджетов — выстраиваются в очередь на flock, а не на CPU. В strace на зависшем FPM-воркере типично видно ожидание flock(... LOCK_EX). Процессор свободен не потому, что «нагрузки нет», а потому что воркеры ждут файл.

В разобранном пике маркетинговой акции (~23:00): CPU около 40%, память в норме, RPS вырос примерно на 30%, Nginx отвечает, а PHP-FPM «молчит» — новые запросы висят. По pm.status_path: все 128 воркеров Busy, listen queue около 340. Оценка конкуренции: сотни одновременных пользователей × несколько AJAX дают тысячи параллельных PHP-запросов, часть из которых блокируется на одном session file.

Порог «тихого» дня: до примерно 100–150 concurrent ещё терпимо; около 200+ с SPA/AJAX-фронтом file lock становится мультипликативным — retry удлиняет очередь. После перехода на Redis-сессии в том же кейсе: p95 каталога 3.8 s → 0.7 s; занятые воркеры 127/128 → 38–42/128; 504 за час акции ~1100 → 0. Сервер «лёг» не от «Meltdown нагрузки», а от очередей на LOCK_EX.

Как подтвердить, что виноваты файловые сессии

Сравнение: диагностика files+flock против бессмысленного апгрейда ядер

Симптом простой: пул Busy при умеренном CPU. Сначала смотрите handler и блокировку файла — не «добавить ядра» и не путать с просто малым pm.max_children.

  1. php -i | grep -E 'session.save_handler|session.save_path' (или phpinfo / pool conf) — ожидаемо ли ещё files.
  2. FPM status: все active при CPU <50% → искать блокировки.
  3. strace -p <pid> -e trace=file,futex на busy-воркер → flock на sess_*.
  4. lsof | grep sess_ — много дескрипторов на session files (в кейсе — тысячи).
  5. В Битриксе: grep -A20 "'session'" bitrix/.settings.php — не переопределён ли handler (file / redis / memcache / database).

Смежный отказ файловых сессий (не lock, а запись): полный диск или inode на session.save_path даёт «плавающий» bitrix_sessid и сбои AJAX CSRF — другая картина, но тот же дефолтный files-path.

Свежий community-кейс (07.08.2026): после restore.php на новую BitrixVM сессии падают с «Could not start session by PHP», потому что в .settings.php остался старый host memcache. Инфраструктура сессий живёт отдельно от факта «сайт открылся».

Быстрый обход без Redis и нормальный переход на Redis

Карточки: раннее закрытие сессии и Redis отдельно от кеша

Временный обход без смены handler: на read-only роутах сразу после чтения сессии вызвать session_write_close() (или session_start(['read_and_close' => true]), если дальше сессию не пишут). В одном разборе среднее ожидание параллельных Ajax упало с 820 мс до 40 мс. Ограничение: на роутах, которые ещё пишут в $_SESSION, раннее закрытие потеряет изменения; при output_buffering закрытие может откладываться.

Через php.ini / FPM pool (phpredis):

Через ядро Битрикс (bitrix/.settings.php, training.bitrix24): с главного модуля 20.5.0+ handlers file, redis, memcache, database (b_user_session). Ключ: 'session' → 'value' → 'handlers' → 'general' → 'type'. Для Redis: type => redis, host/port или servers[]. Если кастомный блок 'session' не задан — обычно идёт нативный PHP session_start() и достаточно php.ini.

Ограничения: что не лечит и что ломает прод

Рост pm.max_children не лечит очередь на flock — только маскирует числом воркеров, пока хватает RAM. Это другой инцидент, чем «мало children и сразу 502».

Метрики, которые отличают этот инцидент: active FPM ≈ max_children при CPU <50%; рост latency у авторизованных / AJAX-heavy URL; session.save_handler ещё files; после смены handler — падение listen queue без апгрейда железа.

Частые вопросы

Почему при акции сайт лежит, а CPU около 40%?

Параллельные AJAX с одним session ID ждут exclusive lock на файл сессии (flock). Воркеры PHP-FPM заняты ожиданием, а не счётом — поэтому процессор и память могут оставаться спокойными при полной listen queue и 504.

Как быстро проверить, что handler ещё files?

Смотрите session.save_handler / session.save_path через php -i или phpinfo, на busy-воркере — strace с flock на sess_*, в Битриксе — секцию 'session' в bitrix/.settings.php. Картина «все FPM Busy при умеренном CPU» указывает на блокировки, а не на нехватку ядер.

Можно ли обойтись без Redis?

Да, как временный шаг: на read-only роутах сразу после чтения сессии вызвать session_write_close() или стартовать сессию с read_and_close, если дальше её не пишут. В разборе ожидание параллельных Ajax сократилось с сотен миллисекунд до десятков. На роутах с записью в $_SESSION раннее закрытие нельзя применять вслепую.

Почему сессии нельзя класть в ту же Redis-БД, что и кеш?

Параметр database в session.save_path должен быть отдельной logical DB. Иначе FLUSHDB (или аналог) на кеше разлогинит всех пользователей. Плюс без AOF/RDB рестарт Redis сам по себе обнуляет сессии.

Поможет ли просто поднять pm.max_children?

Нет как лечение причины: больше воркеров лишь маскирует очередь на flock, пока хватает RAM. Нужна смена handler (Redis / handlers ядра) или снятие лишней блокировки на read-only путях — иначе пик снова соберёт очередь на тех же session files.

Как BX Pulse помогает поймать такой пик

Ситуация «FPM весь Busy при спокойном CPU» — слепой угол, если смотрят только железо и SQL, а сессии годами остаются на files. Имеет смысл заранее видеть занятость пула и очередь до жалоб с витрины и после смены handler — убедиться, что listen queue падает без апгрейда железа.

BX Pulse следит за доступностью и техническим состоянием проектов на 1С-Битрикс и помогает замечать сбои до обращения клиента. Для этой ситуации настройте контроль пула PHP-FPM и уведомление при росте Busy / listen queue при спокойном CPU — добавьте первый сайт.

BX
Команда BX Pulse
Мониторинг и диагностика сайтов 1С-Битрикс
Попробовать BX Pulse