В современном мире цифровых технологий B2B‑порталы становятся неотъемлемой частью бизнес‑процессов многих компаний. Они обеспечивают взаимодействие между партнерами, автоматизируют процесс совершения заказов, упрощают обмен информацией и документами. Однако для того чтобы торговый B2B‑портал мог успешно выполнять свои функции, он должен быть надёжным, быстрым и способным выдерживать необходимые нагрузки.

В этой статье мы подробно рассмотрим одно из нагрузочных тестирований портала Compo B2B, проведенное совместно с компанией Лига Цифрой Экономики. Мы опишем какие инструменты и методики использовались, с какими проблемами столкнулись, как правильно интерпретировать результаты тестирования и почему даже небольшая нагрузка тесно связана с масштабированием.

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

О клиенте

Крупный дистрибьютор автомобильных запчастей для японских, корейских и автомобильных запчастей с филиальной сетью практически во всех крупных городах РФ.

Ключевые метрики проекта:

  • Response Time — время, за которое был получен ответ на запрос (время ответа) в мс. Обычно вычисляются: минимальное, среднее и максимальное время время ответа

  • Throughput — количество запросов за единицу времени, обработанных сервером (пропускная способность). Обычно вычисляются среднее и пиковое число запросов в секунду

  • Перцентиль — метрика, которая показывает значение, ниже которого попадает определенный процент данных (например, перцентиль 95 означает, что 95% запросов были обработаны за время, меньшее или равное этому значению)

  • Transactions Per Second (TPS) — количество операций в секунду

  • Latency — время между запросом и началом ответа

  • Error Rate — процент ошибок в ответах запросов теста

Шаг первый.  Дорожная карта тестирования и тест кейсы

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

При составлении нужно учитывать требования к системе от заказчика (какие показатели он хочет видеть или целевые показатели, результаты хуже которых система не должна выдавать). Также важен контекст тестирования — объект/ы тестирования (что именно нужно выявить: производительность конкретного метода, поведение при определенной нагрузке заявленного функционала и так далее).

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

  • Цели теста производительности. Чего мы собираемся достичь.

  • Масштаб проекта. Каков масштаб проекта, например, количество скриптов, сколько времени нам нужно на тестирование и так далее

  • Архитектура приложения. Детали приложения, такие как сервер приложений, сервер БД, архитектурная схема.

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

  • Настройка инфраструктуры. Данные для настройки тестирования производительности (создание облачной среды, установка инструментов и так далее)

  • Подход к тестированию производительности. Описанный процесс и регламент проведения теста.

  • Критерии входа и выхода. Это очень важно. Мы всегда начинаем тестирование производительности, когда нет ни одного функционального дефекта. Точно так же мы должны понимать, когда мы можем остановить тестирование и подводить итоги.

  • Управление дефектами. Мы используем те же инструменты и методы, которые использует клиент для регистрации дефектов, связанных с тестированием производительности.

  • Роли и обязанности. Подробная информация о заинтересованных сторонах, участвующих в различных процессах во время тестирования производительности.

  • Предположения и риски. Учёт и документирование факторов, которые могут представлять риск для проведения качественного тестирования производительности.

  • Тестовых данные. Подробности о составе и характеристиках тестовых данных и о том, как их необходимо использовать.

  • Временная шкала плана тестирования и основные результаты. Временная шкала разработки сценариев, выполнения теста, анализа и результатов для рассмотрения клиентом.

Шаг второй. Подготовка среды тестирования

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

Apache JMeter — бесплатный инструмент с открытым исходным кодом. Его основное преимущество — гибкость и доступность. JMeter поддерживает различные протоколы, включая HTTP, FTP, JDBC, и подходит для тестирования веб‑приложений, шин данных, тестирования через API и баз данных, тестирования распределенных систем. Позволяет создавать сложные сценарии нагрузки, например, тесты с динамическими параметрами или продвинутую обработку ответов сервера. Предусмотрена возможность интеграции с другими инструментами, поэтому JMeter подходит в том числе для масштабных корпоративных проектов.

LoadRunner — коммерческое программное обеспечение, которое ранее широко использовалось крупными компаниями для проверки производительности их систем. Поддерживает работу с множеством технологий и протоколов, от веб‑приложений до SAP и Citrix. Основной плюс LoadRunner — мощный набор аналитических инструментов. Выдает детализированные отчеты, помогает визуализировать узкие места и прогнозировать поведение системы под реальными нагрузками. В данный момент в большинстве компаний идет переход на open‑source решения.

Яндекс.Танк — это open‑source система для нагрузочного тестирования, которая позволяет создавать и анализировать поведение систем при высоких нагрузках. Яндекс.Танк может использоваться для тестирования различных типов приложений и сервисов, включая веб‑сайты, API, мобильные приложения и другие. Он поддерживает различные протоколы и методы тестирования, что позволяет адаптировать его под конкретные задачи и требования.

NBomber — это бесплатный и открытый инструмент для нагрузочного тестирования, доступный для использования сообществу разработчиков. Использует асинхронные операции для отправки запросов, позволяет работать с различными форматами данных, включая JSON, XML и прочими. Может быть интегрирован с популярными системами мониторинга и анализа, такими как Grafana, InfluxDB и другими

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

Gatling — инструмент простой и масштабируемый, написанный на языке программирования Scala. Gatling позволяет эмулировать большее число виртуальных пользователей в сравнении с Jmeter при равных условиях. Gatling предназначен для создания тестов с многопоточностью и сложной логикой сценариев. Визуализация результатов в формате интерактивных графиков помогает быстро анализировать данные и находить проблемные точки. Инструмент подходит для команд, работающих в Agile, так как позволяет интегрировать тесты в процесс CI/CD.

BlazeMeter — облачное решение, построенное на основе Apache JMeter, расширяет возможности JMeter за счет автоматизации процессов и удобного интерфейса для управления тестами. Аналитические инструменты позволяют быстро оценить результаты и принять решения по оптимизации. Не подходит для тестирования внутри закрытых корпоративных сетей.

Locust — инструмент, ориентированный на разработчиков, которые предпочитают Python. Позволяет генерировать подробные отчеты о времени отклика, количестве ошибок. Locust может использоваться в облачных средах, а благодаря открытому исходному коду его используют многие стартапы и небольшие команды.

Для решения наших задач самый удобный инструмент для нагрузочного тестирования — это Apache JMeter. Его мы и будем использовать.

В данном случае необходимо было произвести тестирование метода, возвращающего информацию о товаре. Было необходимо получить следующие метрики:

1.1. Среднее число запросов в секунду (перцентиль 95)

1.2. Пиковое число запросов в секунду (перцентиль 95)

2.1. Минимальное время ответа

2.2. Среднее время ответа

2.3. Максимальное время ответа

3. Самое долгое время ответа

Также было интересно проанализировать какое RPS выдерживает система.

Для имитации реального поведения пользователей с динамическим изменением количества активных потоков (пользователей) был выбран тип группы потоков — Concurrency Thread Group.

Когда стоит выбирать данную группу, вместо стандартного Thread Group?

Критерии выбора:

  • Плавное увеличение/уменьшение нагрузки (без резких скачков)

  • Поддержка ступенчатого роста пользователей (например, 10 пользователей в секунду)

  • Гибкая настройка времени удержания нагрузки (hold нагрузка)

  • Интеграция с плагином Throughput Shaping Timer для точного контроля RPS (запросов в секунду)

  • Автоматическое завершение потоков после выполнения сценария

Настройка Concurrency Thread Group
Настройка Concurrency Thread Group
  • Target Concurrency — указать максимальное кол‑во пользователей, которые будут одновременно «слать» запросы. В нашем случае = 500

  • Ramp Up Time — время (в минутах), за которое кол‑во потоков должно достичь максимума (Target Concurrency).

  • Ramp‑Up Steps Count — количество «шагов» увеличения нагрузки.

Ramp Up Time и Ramp‑Up Steps Count нужны, чтобы плавно увеличивать нагрузку, а не загружать систему сразу максимальным количеством потоков.

В нашем случае Ramp Up Time = 45 секунд, а Ramp‑Up Steps Count = 10, то есть каждые 4,5 секунды (45 секунд/10 шагов) будет добавляться 50 (500 потоков/10 шагов) активных пользователей. После 45 секунд «разгона» количество потоков станет равным указанному Target Concurrency.

  • Hold Target Rate Time — какое количество минут удерживать максимальную нагрузку (Target Concurrency). Или, проще, время проведения тестирования. Чаще всего есть необходимость выбирать промежутки от 1 часа для показания более точных результатов по «выносливости» системы, но показатели с меньшим временем будут примерно равны первым. В нашем случае держим пиковую нагрузку 15 минут.

  • Thread Iterations Limit — лимит итераций на поток. Если нужно ограничить кол‑во итераций в каждом потоке. В нашем случае не нужно.

Все выбранные значения параметров наглядно отображаются в графике, где вертикальная шкала — количество потоков, горизонтальная — время выполнения тестирования.

По выбранным нами параметрами после «разгона» от 0 до 500 потоков (пользователей) за 45 секунд будут выполняться все 500 потоков одновременно 15 минут.

Для нашего тестирования также было необходимо поддерживать точное RPS (число запросов в секунду). Для этого был настроен плагин Throughput Shaping Timer.

Совместно с Concurrency Thread Group была настроена автоматическая регулировка числа потоков для достижения нужного RPS.

С помощью такой регулировки можно получить имитацию максимально приближенную к реальной нагрузке. Можно плавно увеличивать, уменьшать число запросов в секунду.

Плавно от 10 запросов в секунду до 200 в течении 945 секунд (15,45 минут)
Плавно от 10 запросов в секунду до 200 в течении 945 секунд (15,45 минут)
Плавно от 10 запросов в секунду до 200 в течении 945 секунд (15,45 минут)
Первые 120 секунд (2 минуты) от 10 до 20 RPS, следующие 2 минуты от 20 до 50, следующие 2 минуты от 50 до 100, следующие 2 минуты от 100 до 200, далее 3 минуты нагрузка в 200 RPS и после 3 минуты плавное снижение от 200 до 0.

Также можно держать постоянное RPS всё время теста:

В нашем случае были проведены тесты с плавным увеличением и удержанием на 200 RPS.

В ходе работ учитывалась следующая формула:

Количество тестирующих потоков = RPS × (среднее время ответа в секундах)

С настройкой количества пользователей и числом запросов закончили, теперь нужно определить, как, куда и какие запросы будут отправлять эти самые пользователи.

Чтобы указать формат тела запроса, тип данных и другие параметры заголовков запроса используется Config элемент, в нашем случае — HTTP Header Manager.

Указывается название параметра и его значение.
Указывается название параметра и его значение.

В нашем тестировании формат тела запроса — application/json и соединение закрытое.

Теперь нужно составить сам запрос. Добавляем стандартный Sampler — HTTP Request.

Protocol в нашем случае https. Server Name - сервер продуктового контура.
Protocol в нашем случае https. Server Name — сервер продуктового контура.

Прописываем метод и добавляем параметры. Так как нам необходимо проходиться по разным комбинациям параметров артикула, бренда и кросса — в тест‑план был добавлен Config‑элемент CSV Data Set Config.

В файле присутствуют колонки с необходимыми нам параметрами, комбинации которых будут проставлены в запрос.

Чтобы экранизировать ненужные знаки из файла, мы проставляем галочки «кодировки» напротив параметра в HTTP Request.

Для того, чтобы смотреть результаты тестирования добавлены Listeners:

  • Aggregate Report — для получения среднего, минимального и максимального ответа, также, чтобы следить за Throughput и процентом ошибок;

  • View Results Tree — для просмотра ответов

  • Simple Data Writer — для получения файла со всеми запросами, чтобы найти запрос с самым долгим временем ответа.

Шаг третий и четвертый. Проведение тестирования, анализ результатов и вывод

Тестирование происходило с плавно растущем RPS на виртуальной машине со следующими параметрами:

  • 8 CPU

  • 64 GB RAM

  • HDD 1TB

Показатели росли в соответствии с установленным RPS, нагрузка на процессор составляла около 16%.

После были изменены параметры на 400 RPS в 1000 потоков. Также установлен лимит коннектов БД (Postgresql) = 1000 (ранее он был 500).

RPS начал расти с 380 и дошел до 398. При этом нагрузка снижалась с 65% до 40%.

Отчет Aggregate Report к концу тестирования.
Отчет Aggregate Report к концу тестирования.

После увеличения коннектов, проводилось повторное тестирование с целевым 200 RPS в 500 потоков, но уже без плавно растущей нагрузки, а с постоянной.

Отчет Aggregate Report к концу тестирования.
Отчет Aggregate Report к концу тестирования.

Интересное наблюдение из тестирования. На протяжении всего тестирования максимальное время ответа не превышало 2 секунд, но в какой‑то момент прошел запрос на 21 секунду и среднее время увеличилось. Проблема была найдена, и она заключалась в соединении, а не в отправке и получении ответа на запрос.

График, который показывает, что при 200 RPS 95% запросов обрабатываются меньше, чем за примерно 135 мс.
График, который показывает, что при 200 RPS 95% запросов обрабатываются меньше, чем за примерно 135 мс.

Также на прод контуре были проведены аналогичные тесты с запросами без некоторых дополнительных параметров и также со всеми возможными GET‑параметрами для анализа влияния этих параметров на время ответов.

Итоги по времени ответа и количествам запросов были сформированы в таблицу:

По итогам нагрузочного тестирования мы получили следующие показатели:

1.1. Среднее число запросов в секунду (перцентиль 95) = 184,4

1.2. Пиковое число запросов в секунду (перцентиль 95) = 194

2.1. Минимальное время ответа = 23 мс

2.2. Среднее время ответа = 91 мс

2.3. Максимальное время ответа = 1,5 с

3. Пример запроса с самым долгим временем ответа:

https://хост/метод?login={login}&pass={pass}&art={art}

Также были сделаны следующие выводы:

  • система легко выдерживает 200 RPS и выдают хорошие результаты

  • нагрузка 400 RPS также является стабильной для системы

  • потенциально система может выдержать бОльшую нагрузку

Рад, что дочитали статью до конца и надеюсь, что каждый возьмет из нее что-то полезное! А что бы вы улучшили в этом тестировании? Какие подходы использовали и как бы решили описанные задачи? Поделитесь в комментариях вашим мнением!

Комментарии (0)