Нагрузочное тестирование интернет-магазина 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Нагрузочное тестирование интернет-магазина 1С-Битрикс
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    745
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Нагрузочное тестирование интернет-магазина 1С-Битрикс

Магазин на Битрикс работает стабильно при 30 посетителях онлайн, а при 300 — страницы каталога открываются по 8 секунд, оформление заказа падает с таймаутом, а в логах nginx — 502 Bad Gateway. Владелец магазина узнаёт об этом в первый день распродажи. Нагрузочное тестирование нужно, чтобы узнать потолок до того, как по нему ударишься лбом.

Инструменты генерации нагрузки

k6 — выбор номер один для большинства проектов. Сценарии на JavaScript, минимальное потребление ресурсов (одна машина выдаёт 5000+ RPS), нативная интеграция с Grafana для визуализации в реальном времени. Хранится в репозитории, запускается в CI/CD. Пример сценария для каталога Битрикс:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 100 },   // ramp-up
    { duration: '5m', target: 100 },   // plateau
    { duration: '2m', target: 300 },   // stress
    { duration: '5m', target: 300 },   // hold
    { duration: '2m', target: 0 },     // ramp-down
  ],
};

export default function () {
  // Главная → раздел → фильтрация → карточка товара
  let res = http.get('https://shop.example.com/catalog/electronics/');
  check(res, { 'catalog 200': (r) => r.status === 200 });

  res = http.get('https://shop.example.com/catalog/electronics/?filter_brand=samsung&filter_price_from=10000');
  check(res, { 'filter 200': (r) => r.status === 200 });

  res = http.get('https://shop.example.com/catalog/electronics/samsung-galaxy-s24/');
  check(res, { 'product 200': (r) => r.status === 200 });

  sleep(Math.random() * 3 + 1); // пауза 1-4 сек, имитация реального пользователя
}

Apache JMeter — проверенный стандарт. GUI для создания сценариев, запись через прокси, поддержка cookies и авторизации. Минусы — Java, высокое потребление RAM, один инстанс редко выдаёт больше 1500 RPS. Подходит для команд, привыкших к визуальным инструментам.

Gatling — Scala DSL, неблокирующий I/O, детальные HTML-отчёты с перцентилями. Эффективнее JMeter по ресурсам, но порог входа выше.

Инструмент Язык RAM на 1000 VU Отчёты CI/CD
k6 JavaScript ~200 МБ Grafana / JSON Нативная
JMeter GUI / XML ~2 ГБ Плагины (JTL) Через CLI
Gatling Scala DSL ~500 МБ HTML встроенные Нативная

Четыре сценария, которые нужно тестировать

Нагрузочный тест без реалистичных сценариев — бессмысленная генерация трафика на главную страницу. Для Битрикс-магазина критичны:

Просмотр каталога (60-70% трафика). Главная → раздел → фильтрация → карточка товара. Фильтрация — самое тяжёлое место. Компонент bitrix:catalog.smart.filter при каждом запросе обращается к b_iblock_element_property с серией JOIN по таблицам свойств. На разделе с 1000 товарами и 15 фильтруемыми свойствами — это 30-50 SQL-запросов на один хит. Если компонентный кеш выключен (а он часто выключен «на время отладки» и забыт) — каждый посетитель генерирует полную нагрузку на БД.

Поиск (10-15% трафика). Модуль search использует таблицу b_search_content с FULLTEXT-индексом. На 100 000+ товаров MATCH AGAINST в MySQL деградирует нелинейно. PostgreSQL с tsvector держится лучше, но при конкурентных запросах тоже просаживается. Если используется Elasticsearch — тестируйте отдельно, у него свои лимиты.

Корзина (5-10% трафика). Добавление, изменение количества, применение купона. Каждое действие вызывает пересчёт скидок через \Bitrix\Sale\Discount\RuntimeCache. При 50+ правилах корзины (накопительные скидки, комбо-акции, купоны) пересчёт занимает 200-500 мс. Под нагрузкой это складывается.

Оформление заказа (2-5% трафика, но самый критичный). Создание записей в b_sale_order, b_sale_basket, b_sale_order_props_value, b_sale_payment, b_sale_shipment. Плюс обработчики событий: OnSaleOrderSaved, отправка email, запуск бизнес-процессов. Плюс внешний запрос к API транспортной компании для расчёта доставки. Один checkout — это 50-100 SQL-запросов и 1-3 HTTP-запроса к внешним сервисам.

Deep-dive: профилирование и поиск узких мест

Нагрузочный тест показывает что тормозит. Профилирование — почему.

Xhprof / Tideways — расширения PHP для профилирования с минимальным оверхедом (5-15%). В отличие от Xdebug, можно включать на продакшене под нагрузкой. Xhprof генерирует callgraph — дерево вызовов с временем и потреблением памяти каждой функции. Типичная находка: CIBlockElement::GetList() вызывается 47 раз на одной странице каталога, потому что шаблон компонента дёргает данные повторно.

Подключение xhprof в Битрикс:

// /local/php_interface/init.php
if ($_GET['__xhprof'] === 'on' && CUser::IsAdmin()) {
    xhprof_enable(XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);
    register_shutdown_function(function() {
        $data = xhprof_disable();
        $xhprofLib = '/path/to/xhprof_lib/utils/xhprof_lib.php';
        $xhprofRuns = '/path/to/xhprof_lib/utils/xhprof_runs.php';
        include_once $xhprofLib;
        include_once $xhprofRuns;
        $runs = new XHProfRuns_Default();
        $runs->save_run($data, 'bitrix');
    });
}

Slow query log — обязателен во время нагрузочного теста. Для MySQL: slow_query_log = 1, long_query_time = 0.3 (300 мс — порог для e-commerce). Для PostgreSQL: log_min_duration_statement = 300.

Типичные находки в slow query log Битрикс-магазина:

-- Фильтрация каталога без фасетного индекса
SELECT DISTINCT BE.ID FROM b_iblock_element BE
INNER JOIN b_iblock_element_property BEP1 ON BEP1.IBLOCK_ELEMENT_ID = BE.ID AND BEP1.IBLOCK_PROPERTY_ID = 45
INNER JOIN b_iblock_element_property BEP2 ON BEP2.IBLOCK_ELEMENT_ID = BE.ID AND BEP2.IBLOCK_PROPERTY_ID = 52
INNER JOIN b_iblock_element_prop_m67 BEPM ON BEPM.IBLOCK_ELEMENT_ID = BE.ID AND BEPM.IBLOCK_PROPERTY_ID = 67
INNER JOIN b_catalog_price CP ON CP.PRODUCT_ID = BE.ID AND CP.CATALOG_GROUP_ID = 1
WHERE BE.IBLOCK_ID = 15 AND BE.ACTIVE = 'Y'
  AND BEP1.VALUE_NUM BETWEEN 10000 AND 50000
  AND BEP2.VALUE = '1456'
  AND BEPM.VALUE = '2891'
ORDER BY CP.PRICE ASC
LIMIT 20;
-- Time: 4.2s, Rows examined: 2,340,000

Пять JOIN по таблицам свойств, сортировка по цене, 2.3 миллиона просмотренных строк. На 50 000 товаров это типичная картина.

Blackfire — коммерческий профайлер от SensioLabs. Минимальный оверхед, сравнение между версиями кода, интеграция с CI/CD. Можно задать assertion: «время страницы каталога не превышает 400 мс» — и получать алерт при деградации после деплоя.

Типичные узкие места Битрикс

Компоненты без кеша. bitrix:catalog.section с CACHE_TIME = 0 — каждый хит генерирует запросы к b_iblock_element, b_iblock_element_property, b_catalog_price. Решение очевидно: CACHE_TIME = 3600, тегированный кеш через \Bitrix\Iblock\TaggedCache. При обновлении товара в админке кеш сбрасывается автоматически.

Множественные свойства инфоблоков. Каждое множественное свойство хранится отдельной строкой в b_iblock_element_prop_m{IBLOCK_ID}. Фильтрация по трём множественным свойствам — три дополнительных JOIN. На 50 000 товаров с 20 свойствами таблица свойств содержит миллионы строк. Фасетный индекс (b_catalog_smart_filter) решает проблему, но его нужно перестроить после массовых обновлений каталога.

OPcache. Без OPcache Битрикс компилирует PHP при каждом запросе. Ядро — тысячи файлов. Минимальные настройки:

opcache.enable = 1
opcache.memory_consumption = 256
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0    # на продакшене
opcache.revalidate_freq = 0

Проверка: opcache_get_status(). Если cache_full = true — увеличивайте memory_consumption.

Сессии в файлах. При 500+ одновременных пользователях каталог /tmp/sess_* содержит тысячи файлов. ext4 справляется, но с задержками. Решение — Redis: session.save_handler = redis, session.save_path = "tcp://127.0.0.1:6379".

Агенты Битрикс (b_agent). По умолчанию агенты выполняются на хитах — при загрузке страницы Битрикс проверяет, какие агенты нужно запустить, и выполняет их в контексте пользовательского запроса. Тяжёлый агент (переиндексация поиска, пересчёт скидок) добавляет секунды к времени ответа. Решение: define('BX_CRONTAB_SUPPORT', true) в dbconn.php и перенос агентов на cron.

Ключевые метрики

  • RPS — запросов в секунду без деградации. Для среднего магазина на Битрикс — 100-300 RPS (с кешированием).
  • TTFB — до 200 мс для закешированных страниц, до 500 мс для динамических. Больше 1 секунды — проблема.
  • P95 response time — время, в которое укладываются 95% запросов. Именно P95, не среднее. Если среднее 200 мс, а P95 — 4 секунды, каждый двадцатый посетитель ждёт неприемлемо долго.
  • Error rate — процент 5xx и таймаутов. При превышении пропускной способности error rate растёт резко, не плавно.

Что делать с результатами

Проблема Метрика Решение
TTFB > 1 с на каталоге P95 response time Компонентный кеш + композитный кеш
502 при 200+ RPS Error rate Увеличение pm.max_children в PHP-FPM, тюнинг max_connections в PostgreSQL
Slow query > 2 с на фильтрации Slow query log Фасетный индекс, составные индексы, переход на Elasticsearch
OOM при 300 пользователях Memory usage OPcache, memory_limit per-worker, отключение неиспользуемых модулей
Таймаут при checkout TTFB checkout Асинхронная обработка событий заказа, кеш расчёта доставки

Когда тестировать

Нагрузочное тестирование — не разовая процедура. Запускайте перед распродажами (Чёрная пятница, 11.11, сезонные акции), после миграции сервера, после обновления ядра Битрикс, после массового импорта товаров. k6 в CI/CD позволяет запускать базовый smoke-тест при каждом деплое — 50 VU на 2 минуты, проверка что P95 не ушёл за пределы нормы. Деградация ловится на ранней стадии, а не в день акции.