Меня зовут Валентина, я отвечаю за качество low-code платформы Eftech.Factory в компании Effective Technologies. В этой серии публикаций я честно расскажу о практиках нагрузочного тестирования (НТ), которые мы внедрили у себя. Будет признание реальных ошибок, настоящий процесс НТ и попытки его автоматизации. Те, кто предпочитает видео, могут посмотреть моё выступление на Spring QA Meetup 2024, благодаря которому появился этот текст.
Почему я против жанра Success Story?
В историях успеха нет места для тех глупых и болезненных ошибок, которые мы в действительности совершаем. Success Stories маловероятны. Каждая такая история — это лишь узкая тропинка, которая при определенных условиях может привести вас к победе… В остальных случаях может и не повезти!)
Другое дело — «Failure Stories». Это ситуации, которые вызывают понимающую улыбку и позволяют задуматься, как не допустить подобных ошибок у себя в проекте.
Ошибаться — это нормально. На ошибках учатся) Поэтому я хочу поделиться с вами опытом совершённых мной ошибок.
При подготовке этой статьи я обнаружила, что материал логично разделить на две части:
Поиски оптимального процесса (эта статья).
Прокачка кода и автоматизации (её продолжение, ссылка будет позже).
Почему k6?
В нашей команде для НТ используется решение k6. Эта статья не про поиск лучшего сервиса для НТ, поэтому сравнения и обоснования его использования здесь нет. Я расскажу о процессных ошибках в НТ, которые актуальны для любого сервиса.
Но если вопрос сравнения для вас важен, вот пост от девушки-разработчика, приложившей свою кодерскую руку к k6 и Jmeter и сравнившей их на правах одного из создателей.
Поиски оптимального процесса
Эта статья может восприниматься как «записки Капитана Очевидности», но мне кажется важным поделиться:
ошибками на пути внедрения НТ
вариантом идеального процесса проведения НТ
нашими наработками по автоматизации процесса НТ
Можно идти вслепую и набивать всевозможные шишки…
…или узнать, с какими типами проблем можно столкнуться, и сделать выводы…
Если вы интересуетесь НТ и ищете материалы по этой теме, то у вас, скорее всего, есть конкретные гипотезы, которые вы хотите подтвердить нагрузочным тестированием.
Тут кроется первый подводный камень.
Казалось бы, НТ — это проверка устойчивости и производительности ПО под нагрузкой, сопоставимой с реальными условиями использования.
Но цели НТ могут различаться, а значит, и применяемые подходы бывают разными.
Регрессионное НТ позволяет оценить состояние и показатели вашего продукта по сравнению с прошлыми релизами или новыми изменениями.
Прогнозируемое НТ даёт возможность оценить работу продукта/системы при прогнозируемой нагрузке. Например, если вы ожидаете, что к концу года количество пользователей вашего продукта увеличится в несколько раз, и вам необходимо проверить узкие места и общую готовность продукта к такому потоку нагрузки.
НТ новой функциональности содержит конкретные вопросы к результатам, большой набор метрик и проверок, которые должны помочь в выводах. На мой взгляд, это самый строгий и требовательный вид НТ.
Необходимо подумать и обязательно обсудить с вашей командой, какой из подходов НТ соответствует вашей задаче.
Почему вы уверены, что нагрузочное тестирование поможет в вашей ситуации?
Какие конкретно действия вы планируете предпринять?
По каким показателям/метрикам/графикам вы планируете делать выводы?
Второй важный вопрос: что вы планируете тестировать с помощью нагрузочного теста?
Вы хотите проверить на устойчивость конкретную бизнес-функциональность.
Вы планируете провести E2E тест, чтобы подтвердить свою гипотезу о поведении системы под нагрузкой
Вы собираетесь протестировать маленький микросервис или полноценную платформу.
Почему это важно?
Приведу пример из своей практики. Моя команда занимается разработкой low-code платформы Eftech.Factory.
Платформа состоит из микросервисов, каждый из которых закрывает какую-либо потребность. Пользователи платформы могут собрать своё бизнес-приложение.
Используя визуальный конфигуратор (или low-code), можно создать свои уникальные бизнес-процессы.
В моём случае, требовалось провести комплексное НТ, которое будет проверять и интеграцию с внешними системами, и взаимодействие сервисов между собой, и закрывать кусочки новой бизнес-функциональности для наших пользователей.
В зависимости от того, ЧТО вы будете тестировать, НА ЧТО будете ориентироваться, определятся детали процесса, подходы и подаваемая нагрузка.
В нашей команде мы выстроили следующий процесс:
Груминг
Кодинг
Smoke-запуск
Подготовка к запуску
Замеры
Сбор результатов
Отчёт
Обсуждение результатов
Нет идеальной инструкции, которая убережет от совершения ошибок. Есть рекомендации, которые помогут сэкономить ваши ресурсы — нервы и время…
Груминг
На мой взгляд, странно писать скрипты, проводить НТ и делать выводы в одиночку, ведь две головы лучше, чем одна.
В моей команде этап груминга есть и у разработки, и у DevOps, и у нас, тестировщиков.
Груминг подразумевает подготовку документа с описанием реализации будущего решения и обсуждение планируемых действий с командой.
Лучше потратить время на подготовку и обсуждение, чем на этапе ревью результата или замеров выяснить, что коллеги ожидали совсем другого.
Ещё до начала кодинга я рассказываю команде, какие скрипты я планирую написать. Также я поясняю, какие сервисы и фичи будут под нагрузкой, какую нагрузку планирую подавать и почему именно так. В конце обсуждаем, какие метрики будут фиксировать поведение системы.
Цель груминга — синхронизироваться с командой в ожиданиях и подсветить риски, о которых я могла не подумать.
Как я уже отмечала выше, в процессе груминга у нас участвует вся команда.
Это и разработчики, которые могут подсказать, какая реакция сервиса является нормальной или ожидаемой.
Это и архитектор, который может посоветовать, какие проверки или сервисы стоит исключить или, наоборот, добавить.
В процессе участвует и наш Product, которому на выходе требуется понятный отчёт или график (их я тоже вписываю в ожидаемые результаты).
Как выглядит пример итогового документа с этапа груминга?
Чаще всего это условия будущего кодинга, зафиксированные в свободной форме - например, так:
Груминг нереально меня выручал, когда я слабо представляла, как можно протестировать какой-то конкретный сервис или функциональность. В этом случае на мой верхнеуровневый план работ команда в процессе мозгового штурма накидывала идеи и варианты решений.
Мне не страшно чего-то не знать: если закрываться от советов и и не прислушиваться к коллегам, можно навредить бизнесу.
После ревью плана будущих работ командой, я, засучив рукава, приступаю к кодингу.
Кодинг
Как упоминалось выше, для НТ мы используем сервис k6.
При подготовке статьи я с удивлением узнала, что есть 2 варианта произношения названия сервиса, русский и английский:
КА-Шесть
KeySix
Главное, что мы понимаем друг друга)
Кодинг для НТ практически ничем не отличается от создания автотестов или скриптов для автоматизации рутины. Не будем останавливаться на нём подробно.
Раз уж это «разработка» скриптов НТ, то лучшие практики разработки также следует соблюдать. В их числе:
Подготовка документации и пояснений к скриптам
Ревью кода как тестировщиками-автоматизаторами, так и разработкой
Валидация кода
Обработка и перехват ошибок
И т.д. - не поленитесь погуглить)
Когда скрипт готов, очень советую не торопиться с многочасовым запуском.
Лучше подготовить условия для запуска smoke-нагрузки.
Smoke-запуск
Под smoke подразумевается выполнение написанного скрипта с минимальной нагрузкой и минимальным временем прохождения.
Зачем? Причин сразу несколько:
Убедиться, что на контуре замеров скрипт корректно работает и нет ошибок выполнения.
Удостовериться, что сам контур готов к работе.
Проверить метрики, фиксирующие результаты.
На метриках я тоже «обжигалась».
Казалось бы, очевидно: при готовности скрипта надо убедиться в генерации необходимых артефактов после выполнения замеров, чтобы сделать выводы.
Я прогнала smoke, проверила готовность данных для замера, проверила наличие графиков с результатами. В полной уверенности я на ночь запускаю нагрузку на нашем контуре и спокойно выключаю комп. А с утра я вдруг понимаю, что метрика, которая должна была замерить условия работы бизнес-приложения, не работает. Она пуста. День потерян, и придётся ждать следующей ночи, чтобы после исправления скрипта и метрики запустить замеры заново.
Согласитесь, обидно споткнуться на таком простом шаге.
То есть локальный запуск на 5-10 минут поможет вам убедиться, что дальнейшие часы работы не пропадут зря!
Если smoke прошел успешно, то следующий этап — это подготовка к запуску.
Подготовка к запуску
Да, возможно, это снова Капитан Очевидность в деле. Но пока мы строили этот процесс и составляли чеклисты, много чего произошло — поверьте, на каждый пункт у меня есть история провала!
Итак, чуть подробнее про подготовку.
Инфраструктура
Убедитесь, что ресурсы контура, на котором вы собираетесь проводить замеры, соответствуют требованиям НТ.
Не то чтобы я невнимательный сотрудник (я же все-таки QA!). Тем не менее несколько раз я запускала нагрузку на контуре, где были выставлены минимальные ресурсы с максимальными ограничениями. Из-за этого я получала некорректные результаты, и, опять же, всю работу можно было отправлять на помойку. Как вывод из этой ситуации, наши DevOps создали отдельную таблицу, которая показывает текущие ресурсы контура (request/limit).
Проверьте объём данных на момент старта замеров
Например, если замеров у вас несколько, или их нужно делать какое-то длительное время, то первый замер на чтение может быть сделан на 100 записях в базе, второй замер уже на 1000, а четвёртый уже на 100К.
И показатели, и замеры по времени — всё это отправляется на помойку как невалидные результаты.
Проверьте состав и версии сервисов на контуре нагрузки
Люди
В первую очередь, тут речь про дежурных и DevOps, которые мониторят состояние инфраструры контуров.
При подаче нагрузки сервисы выходят за свои привычные границы потребления. Чтобы лишний раз не тревожить DevOps, я обычно предупреждаю их о проводимых работах.
Несколько раз, запуская нагрузку в течение рабочего дня, я «клала» серверы с базами данных наших тестовых контуров. Часть компании в этот момент шла пить кофе, а DevOps экстренно «поднимали» упавшие сервисы.
Активности
Ещё несколько очевидных, но важных заметок.
Нельзя подавать нагрузку с той же машины, на которой работает сам сервис. Лучше сразу закладывать подачу нагрузки через CI.
Если запуск нагрузки осуществляется через скрипт или CI, подумайте, что может прервать его работу.
Я пару раз споткнулась на том, что не учла время жизни pipeline по умолчанию и время на полноценный замер, из-за чего замеры обрывались по таймауту жизни job…
Подумайте, как можно проверить, что на контуре не возникает “невидимых” скрипту НТ ошибок. Они могут не влиять на нагрузку, но, тем не менее, приводят к деградации вашего сервиса или к деградации работы всего контура.
Автоматизация запуска
Раньше я тратила на замеры несколько дней. Один скрипт выполнялся часа полтора, иногда он мог падать, потому что падал сервис, или количество ошибок превышало заданные пороги. А таких скриптов было несколько.
После нужно было собрать данные, подготовить отчёт, отправить это всё команде на ревью.
А если требовался перезамер, то всё повторялось.
Если замеры надо проводить раз в год, то локальный запуск скрипта и черновые заметки о том, как работает скрипт, допустимы.
Но если в вашей команде НТ — регулярная активность и в анализе замеров участвует команда, то это повод задуматься об автоматизации.
Простейший перенос вашего скрипта в любой сервис CI/CD позволит:
не тратить мыслетопливо, вспоминая, как запустить скрипт и что подставить во входные параметры;
отказаться от тонны документации для передачи своих знаний о работе скрипта коллегам.
Как я писала выше, запуск — это не быстро, от часа и дольше.
В том числе поэтому мы написали небольшого бота, который уведомляет меня о завершении замеров, присылает мне артефакты, ссылки на мониторинг и показатели замеров. В следующей статье разберём логику его работы и посмотрим на код.
Итак, у нас есть скрипты, автоматизация, бот, который вовремя сообщит о статусе запуска замеров.
Следующий этап — это …
Сбор результатов
Метрики подаваемой нагрузки
Какой бы сервис для подачи нагрузки и замеров вы ни использовали, в нём есть свой стандартный отчёт с минимальным набором информации.
На картинке ниже показан пример отчёта от k6:
За какими параметрами надо точно следить:
Скорость выполнения скрипта
Количество выполненных итераций
Итерации, закончившиеся сбоем
Список метрик можно расширить или убрать не критичные для вас.
Состояние машины и тестируемого сервиса
Кроме показателей от k6, мы с командой смотрим в Grafana на метрики тестируемого сервиса:
CPU
Memory
Latency
Error Rate
Невидимые сбои
Есть третий dashboard, который показывает, как себя чувствовал сервис/контур, но уже в разрезе бизнес-функциональности. Это как раз те самые невидимые для НТ ошибки.
Это dashboard ELK (Elastic Stack: (ELK) Elasticsearch, Kibana & Logstash), который выдает ошибки или выводит сообщения между сервисами на контуре за время подаваемой нагрузки.
Удобно, когда со всех сторон можно посмотреть на сервис и контур, на который подавалась нагрузка.
Невидимые сбои
Есть третий dashboard, который показывает, как себя чувствовал сервис/контур, но уже в разрезе бизнес-функциональности. Это как раз те самые невидимые для НТ ошибки.
НТ Процесс | Отчёт
Отчёт с результатами мы храним в Confluence с привязкой к релизам или функциональности.
Что есть в нашем отчёте:
Цель замера
Конфигурация контура (версии, ресурсы, железо)
Итерации замеров и показатели
Ссылки на Grafana/ELK или выгрузки из них
Предварительные выводы и оформленные баги
Важно, чтобы такой документ могли «читать» (понимать) не только вы как непосредственные участники процесса, но и члены команды, и менеджер.
Как я писала выше, у каждого замера есть своя цель, т.е. вопросы, на которые мы ищем ответ с помощью НТ.
Во время замеров могут приниматься решения о перераспределении ресурсов, поэтому важно фиксировать, на какой инфраструктуре проводились замеры, фиксировать причины изменений и финальные показатели.
Сохранять показания каждой итерации может быть нудно, но в ретроспективе это помогает отследить незначительную, но растущую деградацию.
Я как QA фиксирую предварительные выводы, ссылки на борды и баги.
А дальше обязательно показываю этот отчёт всей моей команде.
Для разработчиков это первая обратная связь о работе сервиса. Например, когда парни писали код, то ожидали, что сервис под нагрузкой будет отвечать за секунду, а у меня в отчёте ответ от 5 секунд.
DevOps могут посмотреть на графики и подсветить моменты, на которые я как тестировщик могла не обратить внимания. Утечки, растущая деградация, сбои и др.
Архитектор посмотрит и подскажет, что в каком-то сценарии сервис работает некорректно, или замеры не удовлетворяют «тонкую архитекторскую душу» )
Ну, и менеджер) Ему нужен понятный, читаемый отчёт, в котором выводы очевидны и не требуют пояснений.
Всей командой мы смотрим на результаты и графики, отчёт пополняется замечаниями и выводами участников встречи. Мы принимаем решение: выпускаем релиз или будем оптимизировать.
Собирать отчёт для каждого замера и итерации очень утомительно. Поэтому было принято решение исследовать возможность автоматизации отчётности.
На момент написания статьи замеры от k6 отсылаются в Grafana.
Это позволило результаты k6 из текста в консоли ...
... преобразовать в таблицу.
А благодаря тэгам окружений, можно переключаться между результатами релизов.
Мы ещё не отказались от фиксации результатов в Confluence, но уже сделали хороший шаг в сторону автоматизации отчётности.
Послесловие
В следующей статье я хочу поделиться рекомендациями по автоматизации рутины, отчётности и возможностям кода в нагрузке. Будем говорить только о коде и делиться нашими наработками, которые можно будет забрать себе (gitlab.yml, bot, grafana dashboard)
Надеюсь, ваш старт в НТ будет безболезненным и интересным путешествием!
Буду рада вопросам, комментариям и вашим Failure Stories о работе с НТ.
otchgol
Позвольте не согласиться с главным постулатом статьи: это не статья про тестирование. Это статья - реклама конкретного облачного инструмента. Если инфраструктура готова пустить нагрузку снаружи без vpn это просто безумие, равно как и тестирование продуктового контура, что, впрочем, практикуется с госуслугами, как мы знаем. Тестирование из облаков огромная проблема, с которой не справляются даже агенты в приватном контуре. Результаты тестирования тоже могут попадать под nda и это совсем не редкость. Банки и правительственные органы никогда не готовы к облачным сервисам. Узкий круг использующих нагрузочное тестирование в компаниях РФ скорее ориентирован на JMeter.
cmetikova Автор
Добрый день, спасибо что прочитали статью! Вы меня не так поняли)
У нас обратная ситуация происходила. Когда мы только начинали стартовать в НТ, то пробовали несколько инструментов, и Jmeter в том числе, но после исследования остановились на k6. И мы остановились на бесплатном решении со всем многообразием open source библиотек k6. Запуск реализован внутри нашей инфраструктуры через pipeline CI/CD и на контурах, которые тоже спрятаны внутри.
Я знакомилась с облачным enterprise решением k6. Это конечно космос. Но соглашусь с вами - подавать нагрузку откуда-то из вне, хранить результаты и копию кода на внешних по отношению к компании серверах - крайне сомнительная идея.
Спасибо за ваш комментарий, это навело меня на мысль в след части более подробно пояснить как работает код и как он встроен в нашу инфраструктуру.