Как стать автором
Обновить
323.66
Конференции Олега Бунина (Онтико)
Профессиональные конференции для IT-разработчиков

Нагружать может каждый

Уровень сложностиПростой
Время на прочтение10 мин
Количество просмотров2.8K

Как понять, что нам нужно нагрузочное тестирование? Как быть, если при этом у нас мало опыта и ресурсов? Сегодня обсудим, насколько трудоёмок этот процесс, как не получить гору проблем и не сжечь больше ресурсов, чем хочется.

Меня зовут Ксения Бирюкова, я владелец продукта Платформы Сфера, разработанной холдингом Т1. В одном из моих проектов мы с командой пытались проводить нагрузочное тестирование. Тогда это казалось очень сложным: пробовали тестировать каждый модуль отдельно, связь с legacy-монолитом не помогала, возникали проблемы с написанием генератора псевдо-уникальных персональных данных и многое другое. И хотя результат был достигнут, ресурсов мы потратили гораздо больше, чем планировали. В итоге собрали список ошибок и задумались, как сделать нагрузочное тестирование менее болезненным. Разберём на своих и чужих примерах.

Тестирование объёмов

Одна американская компания, разработав ПО, решила провести нагрузочное тестирование: проверить пропускную способность, скорость ответов и прочее. Они рассчитывали на объёмы до 2 млн записей в базе, предполагалось создание одной копии данных. Во время испытаний ответ занимал в среднем 1,5 секунды, что полностью удовлетворяло требованиям. В реальности же создавалось 20-30 копий, после запуска в эксплуатацию объём данных превысил 50 млн записей, а все запросы стали выполняться более 30 секунд, что приводило к тайм-ауту и дальше по цепочке.

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

Пиковая нагрузка

Одна российская компания реализовала бронирование парковочных мест у себя в офисе. Заранее было известно, что количество сотрудников не превышает нескольких сотен человек. Ребята решили, что нагрузочное тестирование им не нужно, так как нет больших объёмов. Но они не учли, что парковка в центре Москвы вызовет дикий ажиотаж, тем более бесплатная.

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

Это отличный пример того, зачем проверять двух- и трёхкратные пиковые нагрузки.

Стресс-тестирование

Все знают, что крупные разработчики игр уже «собаку съели» на нагрузочном тестировании. Но и они не защищены от проблем. Сразу после релиза одна из команд столкнулась с массовой проблемой невозможности зайти в игру: упала авторизация. В первый раз их поняли, но при запуске следующего проекта проблема появилась снова. Разработчиков завалили целой горой негатива и обращений.

Несмотря на наличие данных об ожидаемом количестве пользователей избежать всех проблем не удалось.Справедливости ради, летом 2023 запуск прошёл гладко. Это отличный пример того, насколько необходимо всестороннее стресс-тестирование.

Лучше три раза проверить, чем два раза упасть.

Процессы и подходы

Все эти истории медленно, но верно подводят нас к сценариям нагрузочного тестирования и способам его проведения.

Классических подходов всего два:

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

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

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

Давайте теперь вернёмся на один шаг назад, после чего сможем сделать сразу два шага вперёд: поговорим о том, как выглядит процесс нагрузочного тестирования и кто должен в нём участвовать. Здесь тоже всё не однозначно, у всех разные цели, разная структура компаний, поэтому единственно верного подхода нет. Например, у крупных компаний уже давно сформировались свои внутренние процессы. Есть новички, которые поступают совершенно иначе, у них есть нестандартные решения либо крутые идеи по оптимизации того, что все уже давно привыкли делать. Мы рассмотрим оба подхода и возьмём лучшее от каждого.

Рабочая группа

Хорошая практика — создать рабочую группу. Её состав зависит от компании, но есть необходимый минимум: разработка, QA, DevOps и бизнес. Уже давно тестирование, тем более нагрузочное, перестало быть зоной ответственности только QA-инженеров. В нём участвуют все заинтересованные подразделения, и важно об этом не забывать.

Обязанность нагрузочного тестировщика — подготовить всё, что нужно: тестовые пользователи, тестовые данные, профили и прочее; провести собственные испытания и передать это дальше. При разборе багов должны помогать DevOps и разработчики; на основе полученных данных бизнес будет принимать решение о том, насколько допустимо или нет релизиться с проблемами. Вся эта цепочка раскручивается в такую схему:

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

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

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

Сделай сам

Вот список основных фич для решения нашей задачи:

С подготовкой тестовых данных нам может помочь синтетическая генерация. При работе с персональными данными нам, скорее всего, потребуются инструменты с сертифицированными алгоритмами обезличивания. Без этого, к сожалению, будет тяжело. Можно создавать шаблоны тестовых скриптов и их переиспользовать по всей компании. Это поможет избежать дублирования кода и облегчит поддержку. Покрыть множество сценариев помогут стандартные профили нагрузки. Проблему проведения НТ на ограниченных мощностях можно решить совместным использованием аппаратных ресурсов и их планированием с помощью специализированного календаря. А зонтичная система мониторинга упростит интерпретацию результатов.

Автоматизация

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

Обезличка и автогенерация

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

Типовые профили нагрузки

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

Чаще всего при проведении нагрузочного тестирования используют либо линейный, либо ступенчатый рост. И дальше уже различные вариации на тему. Но есть и альтернативный подход: стоит также смотреть на количество реальных запросов (чтения и записи) к системе. Это можно сделать с помощью настройки профиля через интенсивность, а не через пользователей.

Сборщики, запись трафика и шаблоны

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

То же самое касается скриптов проверки. Они будут базироваться плюс-минус на одинаковых принципах. Могут переиспользоваться в разных командах и продуктах. Сборщики помогут создать скелет скрипта, на который потом можно нарастить необходимую логику или вообще от всего этого избавиться, сразу использовать перехват трафика, преобразовывать действия пользователя в сценарий. Но нужно быть очень осторожным с этим подходом. Запись трафика поможет получить максимально точное приближение к реальному пользовательскому пути, но вместе с этим вы можете получить много лишних запросов (загрузки картинок, повторы действий). А в финальный скрипт это попадать не должно. Такой подход позволяет снизить порог входа для QA. Если в команде есть новички, джуны, которые не привыкли к написанию скриптов, или появился новый инструмент, то такие фишки помогут быстрее разобраться и снизить проблемы с погружением и входом в проект.

Решение проблем с мощностями

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

Также можно временно совместно использовать ресурсы. У вас может быть несколько проектов, и на всё, естественно, железа не напасёшься. В зависимости от релиза и графиков можно перекидывать оборудование, здесь вам календарь в помощь. Он чудесно решает как проблемы с железом для самой системы, так и с ресурсами генераторов. Можно запланировать свои релизы, выставить их в календарь и избежать потрясающей драки «нам нужнее» или «а нам завтра, а вам вчера».

Ошибки

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

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

На втором месте — настройки по умолчанию. Можно столкнуться с ограничением на количество соединений.

Бронзовый призёр — таймаут. Если вы видели нагрузочное тестирование и отчёты, то на графике среднего времени ответа могли увидеть, как достигается предел в 30 секунд. И чаще всего это говорит о том, что где-то вы забыли про таймаут. К нему приводят долгие запросы в базе. В таком случае стоит посмотреть, корректно ли они настроены.

И последнее место — мониторинг. Это, скорее, не ошибка, а рекомендация: нужно очень внимательно смотреть, как он настроен и как работает. Некорректно настроенный мониторинг будет искажать данные.

Мониторинг генераторов

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

  1. Ресурсы генератора Вы можете захотеть подать нагрузку в 5 000 пользователей, а в генераторе ресурсов — только на 3 000. Если он об этом не сообщит, то все будут в полной уверенности, что всё хорошо, хотя в итоге вы не добьётесь нужных показателей.

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

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

Чем может помочь разработка

Мы обсудили, что и где мы ищем, но остался вопрос: как это можно реализовать? Тут на помощь приходит разработка. Она может разгрузить наших QA-инженеров, которые закопались в отчётах из нескольких систем.

Начнём с архитектуры очень простого микросервисного приложения и пойдём в сторону расширения.

Здесь все запросы поступают в один сервис (шлюз или основной). Он перенаправляет каждый тип запросов своему исполнителю, получает в ответ результат и отправляет его пользователю в обработанном виде. В этом случае определить источник проблем относительно просто. Если ошибки встречаются в большинстве типов запросов, то в первую очередь следует обратить внимание на центральный сервис. Если соседи не страдают, значит, центральный будет не при чём.

А теперь усложним историю и рассмотрим схему поинтереснее — добавим legacy-модуль:

Это пример простой архитектуры, которую кто-то когда-то реализовал. Представим, что она в определённый момент начинает требовать переработки. Причин может быть много.

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

Для исследования такого случая можно проводить изолированное нагрузочное тестирование с использованием mock-сервисов. Суть в том, что за основу берут сервис, работу которого требуется эмулировать, из него удаляют всю бизнес-логику, а ответы на запросы прописывают в коде. В некоторых случаях может потребоваться вариативность в ответах, например, чтобы поместить информацию в БД. И вот тут начинается самое интересное: могут быть узкие места и тонкие моменты. Например, потребуется вариативность ответов, изощрения, чтобы писать информацию в базу. Но я думаю, что команда разработки вполне способна это побороть.

Для нашего примера mock-сервис может применяться в трёх местах:

Когда мы хотим проверить свою обёртку. Изолировав один из новых модулей, мы можем оценить степень его влияния на итоговую проблему. Но чаще всего она возникает в старых модулях, которые куда сложнее изолировать.

Заменяем участок легаси. Здесь две схемы:

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

Способ локализации проблем с помощью разработчиков.

Вместо создания полноценных mock-сервисов, нам может быть достаточно добавить журналирование длительности исполнения отдельных запросов или их частей. Расширенное журналирование также может повлиять на производительность системы, поэтому для таких запросов лучше использовать уровень error.

Почему не подходят стандартные логи? Часто методы содержат дополнительные действия, а мы хотим увидеть длительность выполнения определённого участка кода, например расчёт коэффициента.

Анализ результатов

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

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

В долгосрочной перспективе дополнительную информацию о динамике нам может дать сравнение отчётов. Я лично видела, как два нагрузочных тестирования подряд показывали разницу всего в 3 %, но когда мы подняли старые отчёты, то увидели, что деградация уже достигла 20 %. Динамика и регулярность — это наше всё в нагрузке.

Итоги

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

Видеозапись выступления:

Теги:
Хабы:
+8
Комментарии0

Публикации

Информация

Сайт
www.ontico.ru
Дата регистрации
Дата основания
Численность
31–50 человек
Местоположение
Россия