Специалист по нагрузочному тестированию в Veeam Software: мир больших чисел и дымящихся серверов
Какие задачи решают специалисты по нагрузочному тестированию в Veeam Software? Вот об этом сегодня и поговорим.
Начнем издалека... Основы нагрузочного тестирования
Если усреднить сухие определения из интернета, то получается, что нагрузочное тестирование ставит своей задачей эмулировать нагрузку, создаваемую большим количеством пользователей или операций. А его цель — найти предельные значения производительности тестируемого ПО, при превышении которых его работа перестает быть стабильной.
Нет ничего сложного в том, чтобы взять, например, легковушку, посадить в нее пять человек, в багажник положить три мешка картошки, завести и поехать по прямой. Гораздо важнее понять, какое расстояние она сможет проехать с такой нагрузкой, как поведет себя на разных дорожных покрытиях, когда потребует техосмотра. И не нужны ли ей будут конструктивные изменения. Определение таких вещей значительно важнее для качества продукта, нежели просто поиск предельных значений.
Поэтому предлагаем сойтись на таком определении: нагрузочное тестирование — это определение качества работы продукта под определенной нагрузкой на заданном интервале времени.
Звучит не очень понятно, да? Давайте попробуем развернуть эту мысль. Наша задача — определить, насколько хорошо продукт выдерживает повышение нагрузки, как ведет себя при длительной работе, какие узкие места обнаруживаются, и как их можно устранить.
Продолжая аналогию с несчастной легковушкой, получается, что наша задача — не просто нагружать ее, пока машина не сможет сдвинуться с места, а, постепенно добавляя нагрузку, проверять ее поведение в максимально большом количестве жизненных сценариев. Посадили пассажиров, попробовали тронуться с места. Получилось — хорошо, значит, основная функция продолжает работать штатно. А что будет, если мы так проездим целый день? Если потратим бензина на 30% больше — это допустимо или нет? А если в пять раз больше, тогда что? Как поведет себя машина при подъеме на гору с уклоном в 12 градусов? А если дорога будет не с асфальтовым покрытием, а с грунтовым, и прошел дождь? Вот заехали мы в гору, но как поведут себя тормоза на спуске, и какой длины будет тормозной путь? Эдак может получиться, что класть мешки с картошкой уже и смысла не будет, так как наша машина перестала выполнять свои функции уже на четвертом пассажире, и нагружать ее больше нет смысла.
Роль нагрузочного тестирования в жизни продукта
А так ли важно и необходимо нагрузочное тестирование, как, скажем, проверка основных функций продукта? Ведь, на первый взгляд, это выглядит исключительно как акт доброй воли: продукт работает, нас устраивает качество его основных показателей, и все отлично. Но вот остались у нас еще время и ресурсы для дополнительных проверок, поэтому давайте мы еще себе работы придумаем и проведем тесты под нагрузкой!
Здесь лучше самим себе максимально честно ответить на вопрос: «А что будет, если мы не проведем нагрузочные тесты, и конечный пользователь столкнется с последствиями этого решения?» Особенность нагрузочного тестирования в том, что, когда пользователь подходит к тем самым экстремумам, которые мы можем заранее определить, расширить или ограничить, результат «стреляет» так, что мало не покажется.
Если наш продукт просто перестанет работать в какой-то момент (у машины заглох двигатель, или отвалились все колеса), это мы легко отделались. А если он повредит обрабатываемые данные (отвалилось только одно колесо, машина влетела в столб, и водитель погиб), то что тогда?
Прежде всего, мы должны думать о безопасности людей и их данных. Такие вещи могут приводить к огромным репутационным и финансовым потерям, что в перспективе может привести даже к закрытию компании.
Для продуктов, ориентированных на небольшие компании или объемы данных, нагрузочное тестирование действительно может быть не так критично. Но, когда компания выходит на рынок корпоративных клиентов, где нагрузки на продукт могут быть в десятки раз выше, а финансовые риски измеряться сотнями миллионов долларов, тут уже лучше бы освоить эту область знаний.
Правда, любой опытный тестировщик вам скажет (и будет абсолютно прав), что так называемый Crash Testing проводить надо в любом случае. Хотя бы для того, чтобы знать, что случается при пиковой нагрузке, и спать чуточку спокойней. Но, опять же, если, грубо говоря, это «выстреливает» раз в пять лет и можно пережить неприятный момент, просто заняв выжидательную позицию — это одно. Волна прошла, недовольные побурчали, ситуация стабилизировалась, и можно работать дальше.
С другой стороны, вспомните себя в тот момент, когда выходит ожидаемая вами много лет онлайн-игра. Вы ее купили, заранее скачали, выгнали всех из дома, чтобы никто не мешал вам целиком и полностью насладиться моментом, и вдруг видите, что вы 100500-й в очереди на подключение к серверу, и надо грустно ждать несколько часов. Разработчики могли предсказать наплыв игроков на релизе? Конечно, могли. Они справились с такой ситуацией? И да, и нет. С одной стороны, сервера продолжают работать и выполняют свою главную функцию. С другой стороны, игроки вынуждены ждать в очереди, которая, в свою очередь, не только не дает серверам упасть, но и не дает многим насладиться игрой. Это было обдуманное решение, или просто так получилось? Это абсолютно точно полностью взвешенный и обдуманный ход. Момент релиза — это классический пик нагрузки. Чтобы его сгладить, необходимо докупить очень много оборудования. Но что с ним делать после того, как пик спадет? Как компенсировать эти затраты?
Вот к таким неочевидным вопросам может привести такая штука, как нагрузочные тесты.
В какой момент подключается команда нагрузочного тестирования?
Как выглядит классический жизненный цикл любого продукта: надо собрать требования, оформить их в виде ТЗ, на основе которого разработчики напишут код, а результат их деятельности проверят QA. Затем выносится вердикт об уровне качества итогового изделия. Сразу становится ясно, что под нагрузочные тесты у нас есть время только в самом конце, так как зачем проверять нестабильный продукт под нагрузкой, если его поведение может измениться в любой момент?
Выглядит все очень логично, если бы не одно важное «но»: в современном мире любое ПО — это сложная многокомпонентная система, состоящая из разных модулей, фичей и сервисов. Когда мы добавляем что-то новое в эту систему, это может так повлиять на общую архитектуру, что весь продукт перестанет работать под нагрузкой. Поэтому новые фичи надо проверять заранее и отдельно. Как только появилась более-менее стабильная версия, уже в этот момент ее следует отдавать для нагрузочных тестов. Потому что, если архитектурная проблема всплывет в самом конце, на ее исправление и новые проверки придется потратить несоизмеримо больше сил и ресурсов, чем если бы ее заметили на начальных этапах.
Однако системное и регрессионное тестирование перед релизом никто не отменял. Если сначала ты проверяешь каждый компонент по отдельности, то в конце обязательно надо проверить весь продукт как единое целое. Обычно это довольно сложная и кропотливая работа, так как одновременно нагрузить все компоненты — это не тоже самое, что просто включить все имеющиеся у нас тесты и снимать метрики. Конкретно в случае нашего Veeam Backup & Replication итоговые тесты идут около месяца. То есть строится отдельная лаба, в которой задействуется максимально возможное количество функций, и ведется наблюдение за ее поведением. Запороть такой длительный тест — это, мягко говоря, обидно.
Пишут ли нагрузочники баги?
Итогом труда «классического» тестировщика часто становится список обнаруженных им в продукте проблем и предложенных улучшений. А что остается после нагрузочного тестирования, кроме красивых графиков, из которых можно делать многозначительные выводы? На самом деле, это тоже баги, просто они не могут быть обнаружены другими методами тестирования и несут в себе временные и нагрузочные метрики.
Например: очень долго открывается интерфейс при большом количестве объектов, резкий скачок использования CPU при каких-то условиях, утечки памяти при долгой работе и так далее.
Плюс, как мы уже говорили в начале, только после нагрузочных тестов можно заявить предельные значения, при которых работа продукта была проверена. Проверили одновременный бэкап 10 тысяч машин? Отлично, значит, можно смело писать это в документацию. Обработали миллион объектов инфраструктуры? Еще одна галочка. Смогли одновременно работать с тысячей серверов? Пишем best practices для клиента, как повторить это у себя. Или вы думали, что последние пишутся исходя из каких-то умозрительных вещей? Нет, это все результат тестирования с вдумчивым анализом результатов.
Автотесты vs Нагрузочные тесты
Бытует мнение, что для нагрузочного тестирования достаточно взять уже имеющиеся автотесты и просто немного «допилить их напильником». Если имеем автотест, где проверяем, как работает бэкап на одной виртуалке, то в нагрузочном тесте их должна быть тысяча, и каждая должна быть размером с дом. Вот это мы создали нагрузку так нагрузку! Вот какие мы молодцы!
И такой подход имеет полное право на существование. Особенно в моменты регрессионного нагрузочного тестирования, о котором мы говорили ранее. Автотесты действительно очень важны при анализе стабильных версий продуктов. И тут же становится видно их основное отличие: задача автотестов — покрыть максимальное количество функций в максимальном количестве их вариантов, чтобы вынести вердикт о работоспособности продукта.
Грубо говоря, есть у нас функция бэкапа виртуальных машин. Внутри этой функции есть громадьё вариантов настроек и их комбинаций. И чем большее количество этих комбинаций мы проверим, тем больше мы будем уверены в качестве итоговой функции. Такова задача автотестов.
С другой стороны, у нагрузочных тестов нет задачи проверить все возможные комбинации условий и настроек. Зачастую это и невозможно из-за сложности и длительности экспериментов. Поэтому приходится отбирать ключевые сценарии. Теоретически может случиться, что изменение незначительной настройки приведет к глобальному проседанию показателей, но это уже история про поиск иголки в стоге сена.
Хоть нагрузочное тестирование и невозможно без элементов автоматизации, доля ручных действий в нем остается большой.
Вот пример: стоит задача проверить работу продукта под определенной нагрузкой. Мы пишем скрипт, разворачивающий лабу, и скрипт, запускающий тест, а потом ждем результатов. Если все хорошо и полученные показатели укладываются в наши требования, то все молодцы и получился хороший продукт. Но что происходит, если все сломалось? Отрицательный результат — тоже результат, поэтому наша задача — найти, что именно сломалось, почему оно сломалось, и как это можно исправить. Просто так написать баг и отправить разработчикам нельзя. Они заберут стенд себе и неизвестно сколько будут его держать для поиска причин. Потом они сделают фикс, начнут его проверять, и все это может затянуться на бесконечно долгий срок. Поэтому, засучив рукава, собираем логи, дампы и начинаем сами искать ошибки. Запросто может оказаться, что проблема не в продукте, а в самой лабе. Или есть какая-то бага в операционной системе. Или, к примеру, заканчивается свободная память, и надо понять, сколько ее требуется дополнительно, или как можно снизить утилизацию имеющейся. Это все ручная исследовательская работа, автоматизировать которую не представляется возможным. Во всяком случае, на данном этапе развития технологий.
Правда, в области веб-серверов возможностей для автоматизации нагрузочного тестирования может быть существенно больше. Благо веб-разработка уже который год в тренде, и столкнуться с чем-то действительно уникальным бывает сложно. Если даже в сети не найдется готового теста под необходимый вам профиль нагрузки, его всегда можно допилить или собрать из имеющихся в достатке кирпичиков.
Как стать специалистом в нагрузочном тестировании
Нагрузочное тестирование — это область на стыке нескольких профессий. Тут вам и «классическое» тестирование, и системное администрирование, и автоматизация, и проектирование систем. Опыт в любой из этих сфер поможет быстрее вникнуть и в «нагрузку». Полезно бывает побыть пару лет сисадмином для наработки ИТ-кругозора и технического бэкграунда. Это отличная стартовая позиция, особенно если сам еще не понял, чем именно хочешь заниматься в ИТ. Но и молодой инженер, любящий технику, может прийти в отдел нагрузочного тестирования и научиться всему прямо на месте.
Как это ни странно, но в индустрии контроля качества этих самых подходов к обеспечению качества довольно много. Они могут быть настолько разными, что, проработав в одной компании и добившись там определенных высот, в другой компании этот человек работать просто не сможет из-за разности взглядов на одни и те же вещи. Поэтому в QA принцип «Проще научить молодого специалиста, чем взять готового» остается актуальным, как и много лет назад. Что подводит нас к другому интересному вопросу.
Философия нагрузочного тестирования
Как всем доподлинно известно, суть работы QA не в нахождении багов или попытках сломать продукт. Главная их задача — представить, как тестируемым продуктом будут пользоваться, и проверить, что работа продукта соответствует ожиданиям пользователей. То есть это история про попытки влезть в чужую голову и умение предугадывать желания, о которых сам пользователь еще даже не думал.
Теперь берем нагрузочные тесты. Кажется, что никакой угадайки, а лишь только сплошной прагматизм: собираем ТЗ, основываясь на запросах клиентов, накидываем немножко сверху и начинаем методично проверять необходимые метрики. Но все ломается, как только перед нами встает задача протестировать абсолютно новый продукт, которым еще никто не пользовался. В этот момент задача предугадать поведение пользователей переходит из сферы чисто функциональной в сферу количественную, которая зачастую завязана на чисто технические ограничения. И перед нами встает задача, во-первых, понять эти ограничения, а во-вторых, найти оптимальные методы работы при заданных параметрах. При этом надо постоянно напоминать себе о том, что мы решаем техническую проблему не ради техники, а ради удобства конечного пользователя.
У этой ситуации есть плохая и хорошая стороны. Плохая заключается в том, что если мы делаем нечто новое, чего еще никто не делал, то можем до бесконечности заниматься решением проблем, важность которых пока даже не доказана практикой.
Есть, например, аналитик, который предсказывает, что это должно быть так. А рядом с ним сидит другой аналитик, который требует того же самого, но в два раза больше. А третий вообще говорит, что это никому не надо и достаточно сделать чисто номинально.
Хорошая часть заключается в том, что у нового продукта в запасе обычно есть итерации сбора фидбека и улучшения. Не угадали с парой параметров? Не беда, исправим в патче или следующем релизе. Главное, чтобы на глобальном уровне продукт успешно решал поставленную задачу.
И никто не отменял субъективные метрики из области юзабилити. В какой момент тормозящий UI можно считать проблемой? Насколько ты готов мириться с задержкой реакции на клики? Что вообще такое тормозящий UI? Кто-то считает, что проблема начинается при задержке после клика в одну секунду, а кому-то и семь секунд подождать нормально, если речь про момент пиковой нагрузки.
Получается, что нагрузочное тестирование — это вершина QA-эволюции?
Нет, нет и еще раз нет. Это просто одна из ветвей на дереве возможностей. Между ними нет никакого ранжирования по степени важности из-за разности уровней сложности при вхождении или чего-то такого. Если специалист хочет работать в функциональном тестировании, он развивается в нем. Если хочет больше кода — идет в автотесты. Хочет только код — идет в тестирование кода (да, есть и такое). Хочет мир больших чисел и дымящихся серверов — идет в нагрузочное тестирование. И так до бесконечности. QA — это такая область, где достаточно легко найти приложение своим желаниям.
Да, нагрузочное тестирование требует большего погружения в технику и предъявляет более серьезные требования к знаниям стороннего ПО, чем другие виды тестирования. Но это не делает его лучше или хуже других методик, где больший упор делается на функционально-аналитическую часть, например. Технологичность всего процесса — это просто особенность, которая для кого-то может стать решающим фактором при выборе направления роста.