Нагрузочное тестирование: что? где? когда?

После весны 2020 года слово “тестирование” приобрело некоторые неожиданные значения и неоднозначные коннотации — пожалуй, везде, кроме IT. В нашей сфере без него никуда — и так было всегда.


Видов тестирования ПО — множество: модульное, функциональное, А/В-тестирование, интеграционное, нагрузочное и т д. И на наш взгляд, как раз последнее является как самым важным, так и наиболее сложным. Ведь если ошибки, которые могут быть выявлены с помощью A/B-тестов, модульных, функциональных и интеграционных тестов, проявляются практически сразу после “выкатки” новой версии приложения, то проблемы, на выявление которых нацелено нагрузочное тестирование, — “спящие”. И обнаруживаются они только тогда, когда на новую версию вашего сайта или приложения придет реальный пользовательский трафик, с которым не справится “софтверная” часть проекта (база данных, application-сервер) или “железно-инфраструктурная” (нехватка оперативной памяти в кластере, большая нагрузка на дисковую подсистему при операциях чтения-записи).

В этой статье расскажем и покажем, как мы проводим, пожалуй, эталонное нагрузочное тестирование — в плане полноты покрытия и полноты получаемого в итоге отчёта. Наши наработки вполне воспроизводимы, так что вы можете воспользоваться ими для улучшения работы собственного проекта.

Что? Где? Когда?

Когда необходимо:

  • нужна оценка текущего лимита производительности проекта (например, перед какими-то промо-акциями, рассылками, “черной пятницей” и т д) — чтобы оценить объём временного наращивания мощности и изменения в конфигурации проекта на период акции;

  • вы ищете пути повышения производительности текущей архитектуры/инфраструктуры (поиск проблемных мест / “бутылочного горлышка”) на постоянной основе;

  • нужно проверить новый проект перед запуском в продакшн или новую инфраструктуру  после переезда.
        

Что включено:

  • аудит текущей инфраструктуры,

  • составление сценариев нагрузочного тестирования и выбор инструментов для его проведения,

  • проведение нагрузочного тестирование,

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


Где смотреть:

  • технологический стек — с помощью каких инструментов, ЯП, фреймворков работает проект: это может быть как типичный монолитный веб-сайт на LAMP/LEMP-стеке, так и микросервисный проект, состоящий из 30 сервисов, написанных на различных ЯП (typescript, golang, python…); используется ли какое-либо дополнительное ПО (системы кэширования, системы полнотекстового поиска и т.д.)

  • рабочие мощности — это железные сервера или облачные ВМ с подключенным автомасштабированием, managed кластер Kubernetes и т.д.

  • хранение данных (как БД, так и загружаемые пользовательские файлы) — используется ли on-premise или managed база данных, настроена ли репликация (запись в мастер / чтение со слэйва) и т д. Где хранятся загружаемые пользовательские данные — локальный диск, s3-хранилище и т.д.

  • взаимодействие компонентов проекта между собой — как они связаны, какие подсистемы используются и в каком порядке обрабатывают входящий пользовательский запрос;  если проект построен на микросервисной архитектуре — как сервисы общаются между собой; существуют ли какие-либо внешние зависимости (API платежного шлюза, сервис для email-рассылок), и если да — как осуществляется коммуникация с этими сервисами.

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

    Аудит инфраструктуры помогает лучше понять логику работы проекта, а также сразу найти возможные узкие места, например, синхронный запрос к платежной системе во время оплаты заказа в интернет магазине; отсутствие системы кеширования для статичного контента (страница на новостном портале, включая дополнительный раздел “по этой же теме”). А данные из имеющихся систем мониторинга и сбора логов используем для улучшения сценариев тестирования и поиска узких мест.

Сценарии тестирования и выбор инструментов

Сценарии

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

Когда мы проводили нагрузочное тестирование для “Тотального диктанта”, в сценариях описывали следующие процессы:

  • аутентификация пользователя на сайте,

  • заполнение и промежуточное сохранение диктанта,

  • отправка диктанта на проверку.


Самые частые в нашей практики варианты формирования конечного сценария таковы:

  • заказчик сам формулирует набор сценариев, которые необходимо реализовать — самый идеальный и простой путь :-)

  • сценарии формируются совместно нашими специалистами с командой заказчика — например, если тестирование запланировано перед промо-акцией или регулярной сезонной нагрузкой, и набор критериев более-менее понятен.

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


Инструменты

Наши ТОП-2 — это Яндекс.Танк и Apache JMeter.


Яндекс.Танк — инструмент для проведения нагрузочного тестирования, разрабатываемый в компании Яндекс и распространяемый по лицензии LGPL. В основе инструмента лежит высокопроизводительный асинхронный генератор нагрузки phantom: он был переделан из одноименного веб-сервера, который «научили» работать в режиме клиента. При помощи phantom можно генерировать десятки и сотни тысяч HTTP-запросов в секунду (http-requests per second, http-rps).

На наш взгляд, довольно простой и легкий инструмент для “простых” нагрузочных тестирований: переходы по страницам, без авторизации и прочих дополнительных условий. “Из коробки” позволяет строить графики по результатам нагрузки и предоставлять полноценный отчет о тестировании.


Пример конфигурационного файла для "Яндекс.Танка":

# cat load.yaml 

phantom:

  address: xx.yyy.zzz.qqq:443

  ssl: true

  load_profile:

    load_type: rps # schedule load by defining requests per second

    schedule: const(350, 1000s)

  header_http: '1.1'

  headers: 

     - "Host: test.ru"

     - "Connection: close"

     - "Accept-Encoding: gzip, deflate"

     - "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"

  ammofile: ./test.log_clear

  ammo_type: uri

  package: yandextank.plugins.Phantom

telegraf:

  enabled: false # let's disable telegraf monitoring for this time

overload:

  package: yandextank.plugins.DataUploader

  enabled: true

  token_file: ./token.txt

  api_address: https://overload.yandex.net/

  job_name: test.ru


Пример файла со списком url для конфигурационного файла из примера выше:

# head -n 10 test.log_clear

 

/stat/word/collect/c9cdc1dc-884f-45d3-b5d2-15e35cd1c7e8

/posts/78053

/books/10_non_fiction_knig_ot_noama_khomskogo-912394.xhtml

/world/samye_opasnye_v_mire_morya_8_faktov_o_piratakh_yugo_vostochnoy_azii-1161411.xhtml

/posts/92382

/posts/72761

/signin

/comments/58717

/comments/92382

/comments/92374

 

Пример графиков, генерируемых "Яндекс.Танком" в процессе тестирования 👆🏻

 

Apache JMeter — инструмент для проведения нагрузочного тестирования, разрабатываемый Apache Software Foundation. Хотя изначально JMeter разрабатывался как средство тестирования web-приложений, в настоящее время он способен проводить нагрузочные тесты для JDBC-соединений, FTP, LDAP, SOAP, JMS, POP3, IMAP, HTTP и TCP. Интересна возможность создания большого количества запросов с помощью нескольких компьютеров при управлении этим процессом с одного из них. Архитектура поддерживает плагины сторонних разработчиков, что позволяет дополнять инструмент новыми функциями.

Более тяжеловесный и требовательный к ресурсам инструмент, но обладающий и более широкой функциональностью: позволяет добавлять в http-запросы куки, заголовки (например, для авторизации), парсить страницы для получения значения тех или иных переменных и использования их в последующих запросах; в конечном итоге, даёт возможность полностью эмулировать работу браузера. Мы используем JMeter тремя способами:

  • ручное заполнение плана запросов (добавление урлов, заголовков  и т д),

  • импорт из curl (забираем из консоли разработчика в браузере),

  • прокси (направляем трафик из браузера через JMeter, вручную “прокликиваем” сайт, JMeter на основе этих данных сам составляет план тестирования).

Из минусов — нет встроенных графиков, приходится дополнительно конфигурировать связку с Grafana (что, впрочем, делается довольно легко). Из плюсов — большое комьюнити + большое количество плагинов для тестирования чего угодно (в нашей бигдата платформе мы используем JMeter для генерирования потоковых данных для Apache Kafka и дальнейшей обработки через Apache Spark)

Пример конфигурации JMeter для процесса залогинивания.

Пример конфигурации JMeter для увеличения RPS 👆🏻

 

Примеры графиков/таблиц из настроенной Grafana для Jmeter 👆🏻

Само тестирование и отчёты

После подготовки сценариев и выбора инструментов настаёт очередь самого простого — с организационной точки зрения, но самого ответственного —  точки зрения результата. Да, речь про саму процедуру нагрузочного тестирования. Так как основная его цель — это оценка производительности именно production-окружения, перед запуском тестов необходимо выполнить следующие действия:

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

  • координация с разработчиками / ops-ами — во время тестирования, во-первых, не должно вестись никаких работ по проекту со стороны заказчика (например, деплоя новой версии); во-вторых, в процессе нагрузочного тестирования сайт может полностью “упасть” и необходимо иметь под рукой recovery-план / возможность быстро найти источник проблемы и устранить его.
     

В результате нагрузочного тестирования на выходе мы получаем набор графиков — зависимости времени ответа страницы от RPS входящей нагрузки и утилизации ресурсов в зависимости от RPS, — исходя из которых в финальном отчете мы показываем как текущие возможности/лимиты системы, так и рекомендации по увеличению производительности проекта. Эти рекомендации могут относиться уровню инфраструктуры (отсутствие механизмов автомасштабирования, проблемы на уровне сети) и к уровню архитектуры и кодовой базы (неоптимизированные SQL-запросы, отсутствие индексов в БД, устаревшее ядро bitrix; неоптимальное распределение операций чтения/записи между master/slave БД).

Пример из отчета с рекомендациями по оптимизации SQL-запросов 👆🏻

 

Примеры с рекомендациями по результатам нагрузочного тестирования 👆🏻

 

Интересный пример из практики: клиенту нужна была дополнительная образовательная система для обучения сотрудников, проводили нагрузочное тестирование обеих 👆🏻
 

В чём польза, брат?

Как и любые профилактические проверки, периодическое нагрузочное тестирование будет, несомненно, позитивно влиять на развитие вашего продукта/сервиса. В идеальном мире, при наличии stage(preprod)-площадки, идентичной продакшну, нагрузочное тестирование можно встраивать непосредственно в процессы CI/CD при выкладке новой версии проекта на препродакшн.

Кроме того, оно помогает выявить ошибки как в архитектуре проекта, так и в его кодовой базе. В нашей практике был интересный пример, когда stage-проект, развернутый в managed-кластере K8s, выдерживал всего лишь 8 RPS, а потом падал вплоть дорестартов всех pod’ов деплоймента. После трех итераций нагрузочного тестирования (с разницей в неделю) производительность выросла до 110 RPS.

Резюмируя: в отличие от различных других тестирований (и не только в IT — см. начало статьи), нагрузочное тестирование — это не просто констатация, “болен” пациент или нет, это тотальное и исчерпывающее исследование проекта на предмет узких мест, которые могут стать причиной отказа сайта или сервиса при росте нагрузки. И, в нашем случае, — ещё и дорожная карта по устранению проблем.

Так что берегите здоровье проекта и не забывайте вовремя его проверять!

Готовы обсудить проект?

Ответим на заявку в ближайшие 24 часа. А еще мы можем проконсультировать вас по телефону +7 800 555-91-99, электронной почте info@itsumma.ru или в Telegram-чате.

Свяжитесь со мной здесь
Свяжитесь со мной здесь
❗️Имя не может быть пустым
❗️Телефон не может быть пустым
❗️Email не может быть пустым