Тестирование производительности – это методика тестирования, позволяющая оценить скорость реакции и стабильность работы сервера, сети или приложения под нагрузкой. Этот метод обычно применяют в качестве нагрузочного тестирования. Сегодня все большую важность приобретает время предоставления услуг, которое теперь оценивается как время безотказной работы, а не объем выполненной. Чтобы поддерживать это время стабильным и на высоком уровне, нам необходимо знать свои проблемы с производительностью. Именно здесь на помощь приходит k6.
Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ
Что такое k6? Его преимущества
k6 был выпущен в 2021 году компанией Grafana Labs. Кратко его можно оценить как инструмент, используемый для тестирования производительности и передачи нам результатов этого процесса. K6 создавался с использованием современных технологий, что обеспечило ему ряд преимуществ в определенных областях по сравнению с аналогчными инструментами:
- Скорость и эффективность
- Масштабируемость
- Гибкость сценариев
- Обширные выходные данные и отчетность
В процессе тестирования производительности, как правило, упускается из виду один момент – роль ресурсов и активности, которые затрачиваются на запросы, поступающие в точку произведения измерений. Одним из существенных преимуществ k6 по сравнению с другими распространенными конкурентами, безусловно, является инфраструктура и язык, на котором он разработан.
Если говорить более конкретно, то JMeter по-прежнему занимает лидирующие позиции в этой методологии, но, к сожалению, ему сложно догнать достаточно новые разработки. В качестве примера можно привести сложность и временные затраты на вмешательство в сценарий с помощью PreProcessors и PostProcessors. Именно здесь на помощь приходит k6. Он делает этот процесс достаточно быстрым и понятным благодаря предоставленному CLI.
Концепции k6
В этом инструменте встречаются привычные параметры, которые мы используем во время тестирования производительности и определяем для его работы. Параметры, которые мы будем определять, касаются проведения теста и его результатов. Они задаются в объекте Options
:
- VUs (Virtual Users). Количество пользователей, которые используются/будут использоваться во время тестирования.
- Итерация. Сколько раз каждый отдельный VU будет повторять один и тот же сценарий.
- Duration (Продолжительность). Сколько времени будет длиться тест. Значение указывается в миллисекундах (MS).
- Проверки. Привычные для мира тестов средства утверждения/проверки ответа.
- Threshold (Порог). Пороговое значение, которое мы будем определять во время тестирования. Если фактическое значение превысит его, тест будет считаться неудачным. Например:
thresholds: { http_req_duration: ['avg<150'] }
Пример k6
В примере с k6 мы будем использовать собственные API. Простейшая форма point-load-теста выглядит следующим образом:
import http from "k6/http"; import { check } from 'k6'; export const options = { vus: 1, duration : 1000, thresholds: { http_req_duration: ['avg<150'] }, noConnectionReuse: true, summaryTrendStats: ['avg','min','max','count'] }; export default function () { const url = 'https://test-api.k6.io/public/crocodiles/'; const header = { headers: { 'Content-Type': 'application/json', },}; const response = http.get(url,header); check(response, { 'is status 200': (r) => r.status == 200, }); }
Чтобы лучше понять структуру k6, давайте разделим ее на две части:
- Часть, в которой мы задаем поток теста и то, как он будет себя вести, – объект
options
. - Часть, которая будет являться функцией, в которой будет выполняться тест.
Объект Options
в его простейшей форме можно представить как конфигурацию.
export const options = { vus: 1, duration : 100, // in milliseconds thresholds: { http_req_duration: ['avg<100'] }, noConnectionReuse: true, summaryTrendStats: ['avg','min','max','count'] };
Для простого тестового сценария будет достаточно приведенного выше объекта options
. Среди параметров внутри объекта:
Threshold
гарантирует, что среднее значение выполненных запросов будет больше или меньше определенного значения.NoConnectionReuse
определяет значение keep-alive теста.SummaryTrendStats
определяет форматы значений выходных данных, выдаваемых по завершении тестирования.
Теперь под функцией мы можем назвать место, где будет выполняться тест.
const url = 'https://test-api.k6.io/public/crocodiles/'; const header = { headers: { 'Content-Type': 'application/json', },}; const response = http.get(url,header); check(response, { 'is status 200': (r) => r.status == 200, });
В самом простом виде этот шаг выполняется путем добавления заголовка к сделанному нами запросу GET и проверки его статуса.
Структура сценариев и исполнителей в k6
В k6 исполнитель – это компонент, который определяет, как будет направлена нагрузка во время тестирования. Благодаря этому мы можем легко применять различные подходы тестирования производительности. Таким образом мы получаем возможность контролировать распределение реальных пользователей и увеличение нагрузки на приложение.
Как известно, методика, применяемая в качестве эксплуатационных испытаний, подразделяется на несколько подразделов. Кратко:
- Smoke: низкое значение VUs / 1-5 минут.
- Load: среднее значение VUs / 10-60 минут.
- Stress: высокое значение VUs / 1-2 часа.
- Spike: очень высокое значение VUs / +60 минут.
- Breakpoint: регулярное увеличение VU / +60 минут.
К некоторых случаях для компаний, находящихся на жизненном цикле, одной конечной точки или простого сценария может быть недостаточно для достижения желаемого результата. Чем более простым и базовым является применяемый сценарий, тем меньше разнообразие и вероятность обнаружения проблем.
Самое большое преимущество, которое мы получаем благодаря k6, – это контроль нагрузки внутри, контролируемое увеличение и уменьшение. Это существенно помогает нам в обнаружении проблем в приложении/системе.
export const options = { stages: [ { duration: '30s', target: 10 }, { duration: '1m', target: 20 }, { duration: '2m', target: 0 }, ], thresholds: { http_req_duration: ['avg<150'] }, noConnectionReuse: true, summaryTrendStats: ['avg','min','max','count'] };
Согласно приведенным нами значениям, рабочая логика нашего сценария выглядит следующим образом:
- Общая продолжительность нашего теста составляет 3 минуты 30 секунд.
- В конце первых 30 секунд внутрь начинает передаваться 10 VUs. Затем в течение 1 минуты начинается увеличение нагрузки внутри с 10 до 20 VUs. По истечении 1 минуты начинается контролируемое уменьшение количества VUs внутри с 20 до 0 в течение 2 минут.
- Значения длительности фактически определяют темп нарастания и спада нагрузки, которую мы даем внутри.
- Таким образом, разделив реальную внутреннюю интенсивность на минуты, мы получаем выгоду от сценической составляющей.
Количество запросов в секунду
Другой сценарий, который мы можем создать, – это RPS (Requests per Second). Это тестовая структура, ориентированная на количество запросов в секунду для сценария, который происходит внутри.
export const options = { scenarios: { my_scenario1: { executor: 'constant-arrival-rate', duration: '1m', // test duration rate: 60, // requests to be made according to the TimeUnit we give preAllocatedVUs: 30, // maximum VUs to be used for the given rate value in the test timeUnit: '1s', // how long the given rate value will be applied }, } };
Значение VUs, которое мы указываем, на самом деле не является числом, используемым в начале теста; скорее, в результате примененной скорости тест пытается применяться непрерывно в течение заданного периода времени. Если время отклика увеличивается, продолжает расти и внутреннее значение VUs, чтобы уловить значение скорости, которое мы задаем автоматически.
Стресс-тест
В примере, представленном в этом объекте параметров, мы фактически применяем методологию стресс-тестирования к нашему приложению.
export const options = { stages: [ { duration: '5m', target: 200 }, { duration: '20m', target: 600 }, { duration: '5m', target: 0 }, ], };
Тестирование точек останова
export const options = { executor: 'ramping-arrival-rate', // parameter to control the load to the application stages: [ { duration: '40m', target: 4000 }, // the number of VUs to be reached at the end of the specified duration ], };
Наблюдение за результатами метрики k6
Вместо того чтобы отслеживать и интерпретировать метрики, полученные в ходе тестирования, в текстовом виде, можно визуализировать их на локальной машине. Это позволяет считывать данные приложения в режиме реального времени, что помогает более оперативно выявлять потенциальные проблемы в ходе тестирования.
Мы можем легко создавать наши собственные панели метрик, выгружая выходные показатели k6 по умолчанию на панели мониторинга с помощью Grafana и Influx.
В нашем примере мы будем работать с Docker локально. Давайте настроим Influx на Docker.
Создадим сетевой мост для Docker:
$ docker network create --driver bridge influxdb-telegraf-net
Run Influx на Docker
docker run -d --name=influxdb \ -p 8086:8086 \ -v /tmp/testdata/influx:/root/.influxdb2 \ --net=influxdb-telegraf-net \ influxdb:2.0
Теперь Influx готов к работе на локальном хосте: 8086. При первом посещении этого адреса будет запрошена информация о хранилище и пользователе. Заполните их, чтобы завершить этот шаг.
Расширение k6 InfluxDB
Когда мы устанавливаем k6, он поставляется с поддержкой InfluxDB v1 по умолчанию. Однако в данном примере мы используем InfluxDB v2, поэтому применим расширение.
xk6 build - with github.com/grafana/xk6-output-influxdb
В результате будет создан двоичный файл, обеспечивающий поддержку InfluxDB v2. Далее мы запустим наши тесты с этим двоичным файлом.
Для этого мы можем использовать команду test start
.
K6_INFLUXDB_ORGANIZATION=${organizationName} K6_INFLUXDB_BUCKET=${bucketName} K6_INFLUXDB_TOKEN=${TOKEN} ./k6 run -o xk6-influxdb=http://localhost:8086 ./testScript.js
Тесты, запущенные с этой переменной окружения, будут экспортированы в InfluxDB.
Grafana на Docker
С помощью этой команды вы можете запустить экземпляр Grafana по адресу localhost:3000.
docker run -d -p 3000:3000 --name=grafana grafana/grafana-enterprise
Теперь Influx работает на localhost:8086, а Grafana – на localhost:3000.
Давайте добавим источник данных Influx в Grafana.
После выполнения этих шагов мы сможем запросить Influx из Grafana.
Давайте создадим панель мониторинга. Для этого мы можем использовать данный шаблон. С его помощью мы можем увидеть основные метрики k6.
Теперь наши тесты k6 можно наблюдать через Grafana.
В заключение следует отметить, что тестирование производительности – это важнейшая методология тестирования, позволяющая оценить реакцию системы под нагрузкой и ее стабильность. k6 является мощным и эффективным инструментом для таких тестов. Его преимущества, такие как скорость, масштабируемость, гибкие сценарии, обширные выходные данные и отчетность, – лишь некоторые из важных факторов выбора k6. Благодаря этим преимуществам пользователи могут лучше понять и повысить производительность и стабильность своих приложений.
Рассмотренные нами фундаментальные концепции, установка, использование и различные структуры сценариев k6 являются большим подспорьем для эффективного проведения тестов производительности. Эти возможности обеспечивают успешное завершение тестирования и повышают устойчивость приложения. Помните, что правильное и эффективное тестирование производительности – это залог успеха приложения и удовлетворенности пользователей.
Перевод статьи «Performance Testing and k6».
Пингбэк: Автоматизация тестирования производительности с K6