Всем привет, я Никита Мунтян, QA Load Engineer в inDriver. Пришел в компанию в 2020 году развивать направление нагрузочного тестирования. В первую очередь познакомился с коллегами, выстроил план работы и начал планомерно создавать процессы и технические решения.
Тогда передо мной было пустое поле — делай как хочешь и как видишь, возможностей для творческой реализации много. Оставалось понять, что хотят увидеть от нагрузки, и какой подход использовать. Наша команда решила делать Load as a Service, об этом и расскажу под катом.
Начало
Все началось со встреч о том, что коллеги хотят увидеть от нагрузочного тестирования. В рамках этого этапа мы:
Сконфигурировали тестовый стенд.
Создали регулярные встречи с заинтересованными лицами.
Пришли к выводу, что хотим оптимизировать систему и создать доступный и несложный инструмент, легко поддерживаемый и многофункциональный.
Также мы ввели понятие исследовательского тестирования сервисов, которое использовали как для оценки целесообразности внедрения стороннего софта, так и для разработки собственных решений. Оно применяется для оценки работоспособности сервиса, выделения самых долгих методов и тестирования новых микросервисов, которые активно переезжают с монолита.
Кроме того, мы предложили вариант гибких запусков тестирования: изменения критически важных методов проходят нагрузочное тестирование по запросу от команд, которые уже переехали или собираются переезжать. Периодически мы снимаем профиль и разбираем проблемные места.
В итоге было решено пойти по пути развития нагрузочного тестирования как автоматизированного инструмента для любого заинтересованного лица. Модное-молодежное Load as a Service. Тестировщик или разработчик сможет запускать тесты от команды — красота же! Наша задача, как команды нагрузочного тестирования, предоставить такой сервис.
Для начала мы собрали профили нагрузки, определили критически важные модули и попытались ввести регламенты: при изменении каких методов требуется нагрузочное тестирование. А после этого сделали регламент заведения задач на нагрузочное тестирование.
Вот как выглядит наш шаблон для заведения задачи на нагрузочное тестирование:
Зачем мы хотим нагрузочное тестирование на конкретном проекте.
Название системы и четкое описание работы.
Предполагаемые узкие места.
Ожидаемая нагрузка на систему: какие запросы должны выполняться их RPS. RPS должны быть стандартными и пиковыми (если пока непонятно, можно написать предположительную нагрузку).
Верхнеуровневая архитектура приложения (по возможности).
Описание по шагам, что должен сделать сценарий.
Кто от команды будет заниматься нагрузкой со стороны разработки.
Прикрепить задачу на подготовку стенда и настройке конфигов (от команды).
Также необходимы описания:
Интерфейса, который необходимо нагрузить.
Зависимостей.
Какую загрузку ресурсов мы ожидаем при плановых и пиковых нагрузках.
Минимального периода тестирования (если это тестирование на стабильность).
Основной флоу работы теперь выглядел так:
1. Команда нагрузочного тестирования разрабатывает сценарии, поддерживает стенды, готовит профиль нагрузки и передает знания в команды, выделяя при этом ответственного внутри самой команды.
Например, мы просим техлида команды выделить человека, которого быстро обучат валидировать и обновлять сценарий JMeter. Запуски мы производим через TeamCity.
2. Создается job, который можно вызвать нажатием кнопки. Целью команды нагрузочного тестирования является создание центра экспертизы и помощь в разработке сценариев для команд.
CI-интеграция
Все сценарии хранятся в нашем GitHub-репозитории. Оттуда с помощью Dockerfile и Charts создается loadtests-base-image-контейнер с JMeter в Kubernetes и нужным набором плагинов. А также loadtests-jmeter-job, который использует базовый image для старта job'ы в TeamCity. К сожалению, ямлики с charts и teamplates показать не могу, но эти шаблоны спокойно гуглятся для TeamCity.
Рецепт Dockerfile:
FROM openjdk:8-jdk-slim
#Переменные прокинутые в JMeter
ARG JMETER_VERSION=5.4.2
ENV JMETER_COUNTER='0'
ENV JMETER_SCENARIO=
ENV JMETER_THREADS='50'
ENV JMETER_TIMELINE='10'
ENV JMETER_DELAY='1000'
ENV JMETER_CONTRACTOR='50'
ENV JMETER_CUSTOMER='50'
ENV JVM_ARGS='-Xms16384m -Xmx16384m'
WORKDIR /jmeter
ADD ./scenario/. /jmeter/
Install Jmeter
RUN apt-get clean && apt-get update && apt-get -qy install wget telnet iputils-ping unzip
RUN wget https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-JMETER_VERSION.tgz -C ./ && rm apache-jmeter-JMETER_VERSION/* ./
Install PluginsManager
RUN wget -q -O /tmp/jpgc-casutg-2.9.zip https://jmeter-plugins.org/files/packages/jpgc-casutg-2.9.zip
&& unzip -n /tmp/jpgc-casutg-2.9.zip && rm /tmp/jpgc-casutg-2.9.zip
&& wget -q -O lib/cmdrunner-2.2.jar http://search.maven.org/remotecontent?filepath=kg/apc/cmdrunner/2.2/cmdrunner-2.2.jar
&& java -cp lib/ext/jmeter-plugins-manager-1.3.jar org.jmeterplugins.repository.PluginManagerCMDInstaller
&& bin/PluginsManagerCMD.sh install jpgc-graphs-basic=2.0,jpgc-autostop=0.1,jpgc-graphs-additional=2.0,blazemeter-debugger=0.6,jpgc-functions=2.1,jpgc-graphs-dist=2.0,jpgc-dummy=0.4,jpgc-ffw=2.0,jmeter-grpc-request=1.2.1,jpgc-json=2.7,jpgc-graphs-vs=2.0,jpgc-perfmon=2.1,jpgc-plugins-manager=1.6,bzm-random-csv=0.7,jpgc-redis=0.3,jpgc-tst=2.5,websocket-sampler=1.0.2-SNAPSHOT,websocket-samplers=1.2.8,jmeter-core=5.4.2,jmeter-ftp=5.4.2,jmeter-http=5.4.2,jmeter-jdbc=5.4.2,jmeter-jms=5.4.2,jmeter-junit=5.4.2,jmeter-java=5.4.2,jmeter-ldap=5.4.2,jmeter-mail=5.4.2,jmeter-mongodb=5.4.2,jmeter-native=5.4.2,jmeter-tcp=5.4.2,jmeter-components=5.4.2
RUN bin/PluginsManagerCMD.sh status
ENV PATH /jmeter/bin:" class="formula inline">PATH
COPY entrypoint.sh /
RUN ["chmod", "+x", "/entrypoint.sh"]
ENTRYPOINT ["/entrypoint.sh"]
Вид job, которым стартуют нагрузочные тесты:
Также мы параметризировали количество пользователей и время исполнения самого сценария, используя кастомные threadGroup. Из CI-системы можно было задать параметр, который передавался в JMeter и использовался там, где нужно:
Разработка сценариев
Решено было идти по пути наименьшего сопротивления — инструментом выбрали Apache JMeter. Мы же хотим обучать всех желающих :)
Причины выбора:
Низкий порог входа = актуализация сценариев внутри команды.
Доступность инструмента, огромное количество документации в интернете.
Легкая интеграция в CI.
У нас мобильное приложение, поэтому мы пошли по пути «эмулятор + сниффер для записи сценариев».
Расскажу, как мы создаем сценарии:
1. Открываем Android Studio. У меня их 2 — для записи в один файл действий водителя и пассажира (записать одновременно в оба сертификат не даст, нужно поочередно):
2. Открываем Proxyman. Идем во вкладку Certificate → Install Certificate on Android → Emulators:
Нажимаем на Override Emulator и записываем сертификат на оба устройства:
4. Если все успешно, мы увидим трафик с Remote Devices:
5. Работа с Android Studio + Proxyman:
Устанавливаем последнюю свежую или нужную сборку, и берем 2 устройства:
Возьмем водителя и пассажира, и увидем их запросы в сниффере. Выделяем нужные нам запросы и сохраняем в har file:
6. Используем конвектор har to jmx.
7. Конвертируем файл в jmx и получаем шаблон для работы в JMeter.
Итог
Подключили Grafana и смотрим там основные результаты (RPS, Responce Time и другие показатели).
Прикрутили дашборды на связке Influx + Grafana, подняли сервер, куда складываются стандартные html-отчеты JMeter.
Разместили стенд в Kubernetes, новые микросервисы, которые заходят в эксплуатацию, тестируются перед деплоем. Старые тестируются по запросу от команды при изменениях в определенных методах. Это необходимо для понимания, что будет с инстансом, а также для выявления узких мест. На тестовом стенде все интеграции прямые, с минимумом заглушек.
Собираем системные метрики с помощью Prometheus и Zabbix.
Проводим исследовательские тестирования производительности и идем к полной автоматизации тестов перед деплоем ветки релиз-кандидата в прод.
В конце концов, встал вопрос о том, как сделать процессы более зрелыми. Но об этом я расскажу в следующей статье. Она будет посвящена тому, как мы меняли подходы к тестированию и строили заборы с пайплайнами.
Комментарии (3)
vasiksim88
22.04.2022 09:19Звучит неплохо, надеюсь у вас получилось быстро всех организовать и было много заинтересованных ) Вопросы:
Какие типичные нагрузки подаются в тестах / приходят в Прод? Знаю что Jmeter с синхронным движком много не выдерживает, вопрос - не сталкивались ли с этим
Что с тестированием производительности БД - где проводите, делаете ли копии / наполнение БД прод данными и как ловите там баги производительности?
login40k
Есть много вопросов и комментариев, по большей части по тому что я довольно давно пропагандирую подобный подход и радует, что вы уже в начале пути.
Комментарии:
Кажется, что сервисная история должна упрощать процессы и снижать бюрократизацию, судя по набору требований из таска к вашей команде там у команды появляется очень не сервисная активность в виде сбора и формализации кучи вещей, которые ещё и вероятно будут заставлять их заниматься уточняющей коммуникацией. Мы ходили по такой модели, лучший вариант - это ввести практики которые бы собирали за них весь этот набор или давали бы его в полуготовом виде.
Сами UI-ые скрипты JMeter, конечно имеют преимущество над кодовыми решениями, но степень их поддерживаемости, переиспользуемости и прочих благ очень слабая. Чем больше вариантов каждого теста, чем больше продуктов это становится все сложнее. Нужно поменять креды юзера везде? Нашёл скрипт, открыл на локалке, поменял, закрыл, сохранил, залил. И так с каждым. С аналогичной проблемой сталкивались и мы, тут могу порекомендовать уехать на jmeter-java-dsl если хотите jmeter.
Вопросы:
Почему вы записываете сценарии а не нагружаете апишку в соответствии с тем количеством рпс которое приближено к проду. И если у вас сценарный подход то как вы матчите рпсы с прода и сценарии?
Почему бы не тестировать каждый релиз и каждый сервис, вместо того чтобы рождать сущности в виде регламентом и устраивать охоту на ведьм когда кто-то идёт мимо него?
А кто валидирует результаты тестов и ищет перформанс проблемы? Этому научить например функционального тестера очень ресурсоемко, а если заниматься этим самостоятельно то получиться что при большом количестве релизов вы будете постоянно находится в этом анализе. Мы эту проблему решили собственным анализатором результатов (Quality Gate) который не пустит в прод если есть проблема и сам ее максимально подсветит, чтобы была возможность команде ее самостоятельно решить.
Почему тесты идут с минимумом заглушек? Если надо запустить 2 теста параллельно они ждут когда стенд освободиться? Если это блокирует релиз то это очень негативное влияние на тайм ту маркет
Очень ещё интересно, а много вообще желающих этому обучаться внутри команд?
Если могу помочь - приходи, телегу знаешь)
В целом очень круто, выглядит как набор правильных решений на старте, а чтобы не было больно потом я надеюсь помогут комменты выше)
Kavabungoz
По вопросу №3 можно поподробнее как Вы это реализовали? Невольно вспоминается https://ru.wikipedia.org/wiki/Квартет_Энскомба при взятии в расчет только сухих цифр без анализа графиков.