Введение

Нагрузочное тестирование позволяет выяснить насколько хорошо наш магазин на Magento 2 выдерживает высокую нагрузку, выявить узкие места, как в коде, так и в серверном окружении.

Для магазинов на платформе Magento 2, как и для любых других интернет магазинов, часто характерны резкие всплески нагрузки, которые происходят в начале крупных распродаж, рекламных кампаний и т.д. Нагрузочное тестирование позволяет заранее обнаружить узкие места и исключить возможные падения магазина в такие периоды активности покупателей. Это позволяет избежать возможных финансовых потерь владельцев магазина.

Отдельно можно выделить стрессовое тестирование, при котором нагрузку на сервере увеличивается до отказа. Это позволяет выяснить "предел прочности" нашего магазина и планировать апгрейд серверного оборудования при росте посещаемости в будущем.

В этой статье будет рассмотрено создание нагрузочного теста с помощью инструмента Apache JMeter™, представляющего собой кроссплатформенное программное обеспечение с открытым исходным кодом, написанное на Java.

Jmeter имеет удобный графический интерфейс, позволяющий легко создавать нагрузочные тесты для веб-приложений. Существует большое количество бесплатных плагинов для Jmeter, которые позволяют реализовывать достаточно сложные сценарии, например, оформление заказа в Magento 2.

Jmeter позволяет создавать большую нагрузку на сервер, используя множественно параллельных потоков одновременно.

Составление и отладка тестов

Обычно нагрузочный тест представляет собой набор сценариев, имитирующих поведение настоящих пользователей на сайте. Типичными сценариями для Magento 2 являются:

  • Просмотр главной страницы, категории, товара
  • Поиск товаров по тексту
  • Добавление товара в корзину
  • Оформление заказа
  • Регистрация покупателя

Данная статья ориентирована на тех, кто только начинает своё знакомство с Jmeter, поэтому в качестве примера будет создан простой тест, который будет состоять из двух сценариев:

  • Открытие главной страницы сайта
  • Повторяющийся просмотр страницы товара, url будет взят из csv файла случайным образом

Кроме того, мы разберем процессы отладки, запуска и анализа результатов теста.

JMeter может быть скачан по ссылке https://jmeter.apache.org/download_jmeter.cgi.

Составление тестов и их отладка выполняются в графическом режиме, а запуск теста выполняется через консоль.

Для запуска графического интерфейса нужно запустить файл /bin/jmeter.bat в Windows среде либо /bin/jmeter в системах на базе Linux.

После запуска программа, в левой части будут отображены 2 пустых элемента Test Plan и WorkBench.

Начинаем с добавления Thread Group в Test Plan. Thread Group представляет собой набор потоков (пользователей), выполняющих один и тот же сценарий.

Для добавленного Thread Group указываем следующие настройки:

Name - произвольное название, например "Product page".

Number of Threads - количество пользователей, указываем ${__P(users_product,1)}, такая запись позволит передать количество потоков как аргумент командной строки при запуске теста. Значение этого параметра по умолчанию равно 1.

Ramp-Up Period (in seconds) - указываем время, после которого количество потоков достигает своего максимума, то есть значения из поля Number of Threads. Позволяет избежать резкого скачка увеличения нагрузки, делает ее более плавной. Я обычно указываю значение 30.

Loop Count - указывается количество повторений запусков данной группы, ставим галочку Forever.

Остальные параметры можно оставить по умолчанию.

Получаем такие настройки:

Для эмуляции механизма Cookie и PHP-сессий добавляем компонент HTTP Cookie Manager.

В параметрах компонента указываем Cookie Policy = compatibility.

Подготовительный этап закончен, далее нам необходимо сформировать список HTTP - запросов к нашему сайту. Мы могли бы сделать это вручную, добавляя каждый запрос в дерево элементов, но тогда этот процесс может занять слишком много времени. К счастью, в Jmeter есть удобный компонент который создает прокси-сервер, выполняющий запись всех запросов.

Нам достаточно настроить наш браузер, выполнить на сайте необходимые действия и все наши запросы будут автоматически записаны в Jmeter. При этом эмуляция действий пользователей получается очень точная, включая все асинхронный запросы на странице.

Для записи действия с помощью браузера добавляем в WorkBench 2 элемента HTTP(S) Test Script Recorder и Recording Controller.

Затем

В реальной работе с сайтом пользователи не совершают запросы непрерывно, между ними всегда есть пауза. Для имитации этого поведения в элемент HTTP(S) Test Script Recorder можно дополнительно добавить Gaussian Random Timer

И указать параметры следующим образом:

Теперь паузы между запросами будут также учтены и будут созданы соответствующие элементы при записи действий. В дальнейшем понадобится подправить значение Constant Delay Offset , если в процессе записи они получатся слишком большие.

Настроим HTTP(S) Test Script Recorder.

На вкладе Requests Filtering можно указать правила фильтрации, с помощью которых можно исключить из записи ненужные запросы. Чаще всего не имеет смысла включать в тест запросы к статическим ресурсам, таким как css, jss, изображения и т.д. При использовании CDN в Magento 2 статичные ресурсы будут загружаться с другого сервера и не влиять на загрузку основного сервера. Большое количество запросов к статичным ресурсам усложнит составление и отладку теста, поэтому проще всего их исключить. Сделать это можно с помощь следующих настроек фильтрации:

Теперь необходимо настроить браузер для работы с прокси-сервером. Я использовал браузер Mozilla Firefox. Нужные настройки располагаются в Preferences -> Network Proxy -> Settings. Нужно указать значения как на скриншоте.

Можно начинать запись. Выбираем слева элемент HTTP(S) Test Script Recorder и нажимаем кнопку Start.

Открываем в браузере главную страницу сайта. Если всё было настроено правильно, в Recording Controller появятся новые элементы.

Теперь нужно перенести записанные данные в созданный ранее Thread Group. Добавляем в Product page элемент Once Only Controller

И переносим все элементы из Recording Controller в Once Only Controller. Должно получится следующее:

Повторяем действия для страницы просмотра товара, но вместо Once Only Controller используем SImple Controller.

Тест почти готов, осталось сделать так, чтобы Url для страницы товара выбирался случайным образом из csv файла.

Стоит заметить, что Magento 2 обладает механизмом полностраничного кеширования (page cache, FPC), который может сильно сказаться на результатах тестирования, если не учитывать его. Дело в том, что после загрузки страница будет целиком помещена в кеш, и в дальнейшем запросы на этот же url будут получать результаты из кеша, что сильно снизит нагрузку. При реальной работе магазина некоторый процент страниц в любом случаем будет не закеширован, поэтому важно, чтобы в тесте была достаточно большая выборка страниц.

В Magento 2 есть стандартный файл карты сайта sitemap.xml который содержит список нужных нам url. Я написал простой php скрипт, который позволят сформировать csv файл со списком url к товарам из данного файла.

<?php

$filePath = __DIR__ . '/sitemap.xml';
$data = file_get_contents($filePath);

$exp = '/<url><loc>(.+?)<\/loc>(.+?)<priority>0\.5.+?<\/url>/is';
preg_match_all($exp, $data, $out);
$csv = implode(PHP_EOL, $out[1]);
file_put_contents(__DIR__ . '/categories.csv', $csv);


$exp = '/<url><loc>(.+?)<\/loc>(.+?)<priority>1\.0.+?<\/url>/is';
preg_match_all($exp, $data, $out);
$csv = implode(PHP_EOL, $out[1]);
file_put_contents(__DIR__ . '/products.csv', $csv);

После запуска данного скрипта будут сгенерированы два файла products.csv и categories.csv. Файл products.csv нужно поместить в ту же папку, где располагается сценарий теста (файл с расширением jmx).

Для чтения файла в Jmeter используем плагин Random CSV Data Set. Добавляем нужный элемент в созданный ранее Simple Controller.

Настраиваем как показано на скриншоте:

Находим в дереве элемента запрос к странице товара, и подставляем прочитанный из csv-файла url.

На этом составление теста завершено. Осталось проверить его.

Отладка теста

Добавляем в наш Thread Group компонент View Results Tree.

Выбираем его в дереве элементов и нажимаем. Кнопку Start на панели инструментов.

В левой области экрана будут отображены запросы и их статус. Если всё сделано правильно, результат должен быть таким:

Как видно из скриншота, сначала выполняется один запрос к главной странице, затем происходят последовательные запросы к странице товара. Выбрав мышью любой элемент, можно увидеть заголовки запроса и ответа, результат запроса и убедиться, что все запросы выполняются без ошибок. Данный набор запросов получен для одного потока. При запуске теста с несколькими потоками, эти запросы будут выполняться параллельно для каждого пользователя.

Запуск теста и просмотр результатов

Как уже говорилось ранее, запуск теста нужно выполнять из командной строки. Для этого нужно выполнить команду:

bin/jmeter -n -t ~/jmeter/Test\ Plan.jmx -l ~/jmeter/result.jtl -Jusers_product=10

Здесь указывается путь к файлу сценария и путь для сохранения файла с результатами. Кроме того, мы передаем количество пользователей, используя наш кастомный параметр users_product.

После запуска команды в консоли будет отображена информация о текущем состоянии теста : количество запущенных потоков, количество запрос в секунду и прочее.

Мы можем остановить тест, нажав Ctrl + C, результат будет сохранен в указанный в команде файл.

Для просмотра результатов теста Jmeter есть несколько компонентов, которые позволяет просматривать статистику теста как в табличном так и графическом виде.

Например, для просмотра общей статистики в табличном виде можно использовать компонент Summary Report.

Сначала нужно добавить компонент в WorkBench:

После чего нужно указать путь к файлу с результатами в поле Filename:

В заключение хотелось бы отметить, что запускать тест на production-сервере следует с осторожностью, внимательно следя за показателями сервера. Для этого очень полезным будет такое средство мониторинга как NewRelic.

Надеюсь, данная статья поможет вам при создании собственных нагрузочных тестов.