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

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

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

Далее можно узнать чуть больше обо всех ужасах.

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

Нагрузочник — чуть-чуть разработчик. В зависимости от задачи иногда нужно читать и писать код вне зависимости от опыта с языком и технологией. Мне уже пришлось поработать с несколькими ЯП: java, scala, groovy, kotlin, c#, javascript, etc. 

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

И да, слово «бизнес», если решите уйти в нагрузку, будет вводить вас в лютый ступор и вызывать желание уехать в глухие леса Сибири. Сейчас поймёте сами почему.

Кто приходит в нагрузочное тестирование? 

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

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

Реже в нагрузке можно увидеть разработчика. Нет причины, кроме “так вышло”.

Чаще всего в нагрузку попадают из администрирования. Вероятно потому, что администратор чаще других сталкивается с документацией, скриптами, конфигурациями и, что важнее, планированием ресурсов.

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

Вам постоянно не хватает времени

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

Вариант первый и самый популярный: что-то «бахнуло» на продуктовой среде и вам срочно нужно это воспроизвести, рассказать, что именно стало причиной и дать рекомендации по устранению. Звучит просто, но дьявол кроется в деталях.

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

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

Кстати, на эту тему ещё очень смешно ссылаются на «time to market». Это забавно, потому что вывод продукта без представления о производительности может стоить дороже, чем вывод сырого продукта. Есть вариант “канареечного тестирования” и порой он даже работает. Так, для примера, работает один достаточно популярный сервис объявлений, насколько мне известно.

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

Такие проекты, как правило, «горящие». Всё, что может выручить – огромный практический опыт и знание теории.

Недооценённая сложность работы

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

В моей практике был случай, когда мне на тестирование принесли сайт ДБО, где для аутентификации использовался SRP-6a. Штука в том, что при этом методе нужно программно выполнить череду преобразований входных данных и отправить их в следующем запросе.

Я не имел представления о сложности реализации аутентификации и не сразу догадался заглянуть в js файлы, а только на третий день. И потому делал аутентификацию две недели из запланированной недели на полный цикл проверок из экспериментов по поиску максимума и проверки стабильности. Если вам в голову пришёл вопрос из разряда “а чо ты его делал? чо эт не тот, кто писал код”, то ответ прост — на тестирование приносят не только свои разработки, но и вендорский продукт. И далеко не всегда есть связь с вендором. В моём случае вендор сообщил, что когда-то очень давно писал плагин для старой на тот момент версии Apache Jmeter, но его не даст.

Справедливости ради, мой менеджер вовсе предложил тестировать  производительность при помощи Selenium. Никогда так не делайте! Вам прямо очень больно будет при отслеживании важных метрик, вроде времени ответа. Ресурсов при этом потребуется многократно больше. Если вам непонятно, почему это больно, то ещё раз: ресурсов надо раз эдак в 50 больше для генерации нагрузки, потому что вместо одной софтины, которая запросы отправляет, вам нужно запускать пачку браузеров, которые вы не можете контролировать полноценно. И как прикажете контролировать интенсивность запросов? А хочется ли на каждый запрос писать отдельную проверку ответа? А сильно ли удобно делать корреляцию? А заново реализовывать пересчёт количества ошибок, времени ответа, времени ответа для процента запросов, задержки и тому подобное? Просто примите как аксиому - тестировать таким способом - плохой путь, ведущий в бездну отчаяния и некорректных результатов.

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

Очень долгий анализ 

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

Почему так может случиться? Желанием заказчика или политикой департамента может быть эксперимент в интеграции с другими «живыми» системами. В этом случае, вместо ряда заглушек, в качестве зависимостей, придётся установить и настроить эти самые системы. У них могут быть свои интеграции, каждую из которых потребуется проанализировать и так или иначе реализовать. Чаще всего надеяться на службу поддержки не приходится. Как правило, если это не согласовано сразу, они помогают по остаточному принципу, исходя из своих задач и желания. Поэтому чаще всего именно нагрузочник знает о системе несколько больше, чем сами разработчики и аналитики, потому что ему приходится проходить весь путь по тем следам, что ему оставляют.

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

Очень долгая подготовка скриптов

После того, когда вы уже выполнили предыдущие этапы и приступили к непосредственному написанию действий в своих скриптах, можно провести немало времени в такой вещи, как корреляция. Нагрузочники работают с любыми данными и протоколами, которые ранее были придуманы. Иногда для этого даже приходится создавать собственные инструменты (Yandex Tank, Apache Jmeter, например). Расскажу об одном из случаев.

Это был Correqts, который в тот момент, не знаю как сейчас, использовал JSON массив. И это был именно массив — к нужным значениям в нём можно было добраться только по индексу, который перед этим нужно было вычислить. Представьте себе, что вам приходится последовательно вычислять в среднем семьдесят индексов для десятка таких JSON. Очевидно, есть какие-то правила, по которым было бы проще работать с такими документами, но в тот момент я так и не смог их выявить и работал с абсолютными положениями значений в документах. Правда, несколько позже, я нашёл ключевые слова в значениях, получаемых по индексу (не ключи, по которым можно получить значение, а именно значения) и создал код, который позволял использовать эти значения для перемещения по массиву подобно тому, как это происходит в XPath.

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

Некоторые сложности с тем, что говорили об одном, потом пришли с претензией о другом

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

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

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

Абсолютно успешно обстреляв сервис, собрав данные из мониторинга и написав по нему отчёт, я отдал итоговый документ с выводами заказчику.

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

Некоторое недоразумение с объёмом работ

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

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

Значения были получены и отданы, а радостный владелец продукта с галочкой «результаты получены» выкатил сервис, где тот через несколько часов лёгкой нагрузки стал стабильно падать. По этой причине товарищи из бизнеса стали задавать логичные вопросы, на что он стал яростно стучать ножками и винить нагрузочников.

Нагрузку обвинили во всех грехах, начиная от планирования ресурсов (хм, с чего это вдруг?), до некорректной настройки. К слову сказать, нагрузочники могут играться с настройками приложений, сетей, ОСей и прочим. Всё во благо успеха! Однако, как нас предупреждает сама теория тестирования, полное покрытие невозможно. Время всегда ограничено.

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

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

Рука – лицо

А помните, в самом начале я говорил про важность анализа? В самом начале своей карьеры (только – тсс!) я допустил ужасную ошибку – не до конца исследовал систему, которую нужно было тестировать. И вот момент истины – окружение готово, заглушки написаны, скрипты и сценарии есть! Ступень за ступенью я поднимаю нагрузку и вдруг, неожиданно, результаты окрашиваются в алый красный. Но в мониторинге всё хорошо и проблем нет. Я начинаю инспектировать ответы и обнаруживаю long polling, что значит, что я получаю успешные ответы, но сообщающие мне, что нужно повторить запрос немного позже. Но мои скрипты никак не готовы были к такому повороту.

Это самый стыдный результат.

В заключение

 

На самом деле не всё так страшно, как это кажется.

Действительно, иногда придётся сильно нервничать. Иногда придётся откровенно отстаивать свою позицию. А иногда даже принять всю ответственность за свои ошибки.

Однако если вам страшно принять всё это, то работать становится абсолютно негде. ИТ, как и любая другая отрасль, кроме науки, не более чем ремесло в 99% случаев, когда весь процесс — это почти одинаковые на выходе продукты и действия.

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

Так, для примера, за три года я работал с продуктами, написанными на разных языках и имеющих особенности. Один был монолитом, написанным на Scala и подход к нему был стандартный JVM’овский. Он жил себе на живом сервере и работал на нём изолированно, что позволяло мониторить только показания ОС и JVM. Мне приходилось создавать доски в Grafana для отслеживания состояния java-машины, собирать руками логи и ловить долгие запросы в PostgreSQL через лог долгих запросов.

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

Следующий же проект уже был микросервисным, упакован в контейнер и работал в k8s, написан на Python с использованием Django. То есть для анализа необходимо отслеживать работу хоста, контейнеров, базы данных и самой софтины.

Вслед за тем появился проект, который использовал Mesos и Marathon для оркестрации контейнеров. Внутри контейнеров находилось всё, от Redis в качестве кэша, до сервисов, работающих в JVM.

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

За это время мне пришлось поработать с PostgreSQL, Redis, Mongo, Kafka (да, её тоже иногда используют в качестве хранилища). Для каждой базы своя специфика, начиная от принципов, - реляционная и нереляционная, - заканчивая синтаксисом и протоколом.

Grafana с различными источниками данных (InfluxDb разных версий, например, отличается синтаксисом, а Prometheus использует собственный PromQL). Ops Manager, когда нечем больше отслеживать работу MongoDB.

Стоит ли упоминать про разнообразие сред для работы с базами данных? Про то, как занимательно осваивать инструменты для работы через CLI и каким разным может быть набор для одних и тех же действий? (только для примера: Mongo Compass - единственный из бесплатных может делать экспорт результатов выполнения запросов, которые здесь называются конвейерами, в CSV файл, который потом можно использовать для параметризации запросов)

На самом деле, в зависимости от проекта, помимо инструментов для анализа, сбора и работы с данными может меняться и сам нагрузочный инструмент. Если я обходился в большинстве случаев Apache Jmeter, то теперь пришлось пересесть на LoadRunner - закрытый и неудобный (IMHO) в плане создания и редактирования скриптов. Смена инструмента может происходить почти мгновенно в зависимости от проекта и для каждого нужно выбирать подходящий. Для кодеров это может быть какой-нибудь gatling, k6 или что-то вроде locust.

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

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