«Сайт упал в Чёрную пятницу». «API не выдержал наплыва пользователей после рекламы». «Приложение тормозит, когда больше 100 человек онлайн». Знакомые истории? Нагрузочное тестирование — это способ узнать о таких проблемах до того, как о них узнают ваши пользователи. По данным исследований, компании вроде Etsy, использующие автоматизированное нагрузочное тестирование в CI/CD, ловят до 90% проблем производительности до продакшена. Apache JMeter и Gatling — два самых популярных инструмента для нагрузочного тестирования. В этой статье разберёмся, что это такое, какие типы тестов бывают, как настроить первый тест в каждом из инструментов, и — главное — какой выбрать именно вам.
1. Что такое нагрузочное тестирование
Определение
Нагрузочное тестирование (Load Testing) — это тип тестирования производительности, который проверяет, как система ведёт себя под ожидаемой нагрузкой. Цель — убедиться, что приложение справляется с запланированным количеством пользователей, сохраняя приемлемое время отклика и стабильность.
Зачем нужно
| Цель | Что даёт |
|---|---|
Найти bottlenecks | Определить, где система «захлёбывается» под нагрузкой |
Capacity planning | Понять, сколько пользователей может выдержать инфраструктура |
Валидация SLA | Проверить, что система соответствует требованиям по времени отклика |
Предотвращение инцидентов | Найти проблемы до того, как они ударят по пользователям |
Оптимизация | Данные для настройки серверов, БД, кэширования |
Нагрузочное тестирование vs Performance Testing
Performance Testing — общий термин, включающий разные типы тестов производительности. Load Testing — один из них.
Performance Testing включает:
• Load Testing — тестирование под ожидаемой нагрузкой
• Stress Testing — тестирование за пределами нормальной нагрузки
• Spike Testing — тестирование резких скачков
• Soak/Endurance Testing — длительное тестирование
• Scalability Testing — тестирование масштабируемости
• Breakpoint Testing — поиск точки отказа
2. Типы нагрузочных тестов
Load Testing
Классическое нагрузочное тестирование: проверка системы под ожидаемым количеством пользователей. Цель — убедиться, что приложение работает корректно при нормальной нагрузке.
| Параметр | Описание |
|---|---|
Нагрузка | Ожидаемое количество пользователей (например, 1000 concurrent users) |
Длительность | Обычно 15-60 минут |
Что измеряем | Response time, throughput, error rate |
Когда применять | Перед релизом, после крупных изменений |
Stress Testing
Стресс-тестирование выходит за пределы нормальной нагрузки, чтобы найти точку отказа и понять, как система ведёт себя на пределе возможностей.
Цитата: «Стресс-тестирование — популярный тип нагрузочного тестирования, который оценивает, как система работает при нагрузке выше обычной. Системы могут получать повышенную нагрузку: дедлайны, зарплаты, час пик, конец недели и многие другие ситуации.»
Что выявляет: проблемы синхронизации, утечки памяти, race conditions.
Spike Testing
Spike-тестирование проверяет, как система справляется с внезапным резким ростом нагрузки — например, когда реклама на ТВ приводит миллионы пользователей одновременно.
| Сценарий | Пример |
|---|---|
| Продажа билетов | Концерт Taylor Swift — миллионы в очереди одновременно |
| Запуск продукта | PlayStation 5 — очередь на предзаказ |
| Реклама на ТВ | Super Bowl — сайт рекламодателя |
| Сезонные распродажи | Black Friday, 11.11 |
| Дедлайны | Последний день подачи налоговой декларации |
Цель: проверить эластичность системы — может ли она масштабироваться вверх при пике и вернуться к норме после.
Soak/Endurance Testing
Длительное тестирование под стабильной нагрузкой (часы или дни). Цель — найти проблемы, которые проявляются со временем: утечки памяти, деградация производительности, накопление ошибок.
Breakpoint/Capacity Testing
Поиск точки отказа: постепенное увеличение нагрузки до момента, когда система перестаёт справляться. Помогает понять реальную capacity системы.
Breakpoint Test:
Начать с 100 пользователей → Добавлять по 100 каждые 5 минут → Мониторить response time и error rate → Зафиксировать точку, где response time резко растёт или errors > 1%
3. Ключевые метрики
Response Time (Время отклика)
Время, которое сервер тратит на обработку запроса и отправку ответа. Основная метрика пользовательского опыта.
| Метрика | Описание | Использование |
|---|---|---|
Avg Response Time | Среднее время отклика | Общая картина, но скрывает outliers |
Min / Max | Минимальное / максимальное время | Границы, но max может быть аномалией |
Median (P50) | 50% запросов быстрее этого значения | Типичный опыт пользователя |
P90 / P95 / P99 | Перцентили | Опыт «худших» пользователей |
Почему перцентили важнее среднего
Факт: «Один запрос с временем отклика 20 секунд может исказить среднее время всего приложения, даже если 7 из 8 запросов обрабатываются за 107 мс.»
Средние значения скрывают проблемы. Перцентили показывают реальную картину:
| Перцентиль | Что показывает | Когда использовать |
|---|---|---|
P50 (Median) | Типичный опыт | Базовая метрика |
P90 | 10% пользователей ждут дольше | Хороший индикатор UX |
P95 | 5% пользователей ждут дольше | 🟢 Рекомендуется для SLO |
P99 | 1% пользователей ждут дольше | 🟢 Критичные системы (финансы, медицина) |
Совет: Не определяйте SLA через средние значения. Используйте формулировку: «Сервис должен отвечать менее чем за 1 секунду для 99% запросов».
Throughput (Пропускная способность)
Количество запросов, обработанных в единицу времени. Измеряется в requests/second (RPS) или transactions/second (TPS).
| Throughput | Интерпретация |
|---|---|
| Стабильный | Система справляется с нагрузкой |
| Падает при росте users | Bottleneck, система насыщена |
| Растёт линейно с users | Система масштабируется хорошо |
Error Rate (Процент ошибок)
Доля запросов, завершившихся с ошибкой (HTTP 4xx, 5xx, timeouts).
| Error Rate | Оценка |
|---|---|
| < 0.1% | 🟢 Отлично |
| 0.1% - 1% | 🟡 Приемлемо |
| > 1% | 🔴 Требует внимания |
| > 5% | 🔴 Критично |
Другие важные метрики
Concurrent Users: Количество одновременных пользователей
CPU/Memory Usage: Утилизация ресурсов сервера
Network I/O: Использование сети
Database Connections: Пул соединений с БД
Queue Length: Длина очередей (если есть)
4. JMeter vs Gatling: сравнение
Общее сравнение
| Критерий | Apache JMeter | Gatling |
|---|---|---|
Год создания | 1998 | 2012 |
Язык | Java | Scala (Kotlin/Java также) |
Подход | GUI + XML | Code-first (DSL) |
Архитектура | Thread-based (1 thread = 1 user) | Async, event-driven (Akka) |
Потребление ресурсов | Высокое | Низкое |
Кривая обучения | Низкая (GUI) | Средняя (нужен код) |
Протоколы | HTTP, FTP, JDBC, LDAP, JMS, SOAP и др. | HTTP, WebSocket, JMS, MQTT |
CI/CD интеграция | Через плагины | Нативная (Maven/Gradle) |
Отчёты | Базовые + плагины | Красивые HTML из коробки |
Лицензия | Apache 2.0 (бесплатно) | Apache 2.0 (бесплатно) |
Архитектурные различия
JMeter (Thread-based):
• 1 виртуальный пользователь = 1 поток
• Больше пользователей = больше памяти и CPU
• При 1000+ пользователей требуется distributed testing
Gatling (Async/Event-driven):
• Использует Akka actors и Netty
• Один процесс может симулировать тысячи пользователей
• Меньше потребление ресурсов при большой нагрузке
Когда выбрать JMeter
✅ Команда без опыта программирования
✅ Нужен GUI для визуального создания тестов
✅ Тестирование не только HTTP (JDBC, FTP, LDAP, JMS)
✅ Богатая экосистема плагинов
✅ Небольшие и средние нагрузки (до 1000 users на машину)
✅ Нужна запись сценариев через прокси
Когда выбрать Gatling
✅ Команда разработчиков (code-first подход)
✅ Высокие нагрузки (тысячи concurrent users)
✅ CI/CD пайплайны (тесты как код, версионирование)
✅ Тестирование API и микросервисов
✅ Важна эффективность ресурсов
✅ Нужны красивые отчёты из коробки
Вердикт: «Оба инструмента поддерживают большинство требований, так что это скорее вопрос личных предпочтений и опыта команды.»
5. Apache JMeter: быстрый старт
Установка
Требования: Java 8 или выше
Скачать: jmeter.apache.org
Распаковать архив
Запустить:
bin/jmeter.sh(Linux/Mac) илиbin/jmeter.bat(Windows)
Структура Test Plan
| Элемент | Назначение |
|---|---|
Test Plan | Корневой элемент, контейнер для всего теста |
Thread Group | Группа виртуальных пользователей |
Sampler | Запрос к серверу (HTTP Request, JDBC Request и т.д.) |
Config Element | Настройки (HTTP Defaults, Cookie Manager) |
Assertion | Проверка ответа (Response Assertion, Duration Assertion) |
Listener | Сбор и отображение результатов |
Timer | Задержки между запросами (think time) |
Создание первого теста
Шаг 1: Создать Thread Group
Thread Group определяет количество пользователей и режим нагрузки.
ПКМ на Test Plan → Add → Threads (Users) → Thread Group
| Параметр | Описание | Пример |
|---|---|---|
Number of Threads | Количество виртуальных пользователей | 100 |
Ramp-Up Period | Время для запуска всех пользователей | 60 сек |
Loop Count | Сколько раз каждый пользователь выполнит сценарий | 10 или Infinite |
Шаг 2: Добавить HTTP Request Defaults (опционально)
Общие настройки для всех HTTP запросов в группе.
ПКМ на Thread Group → Add → Config Element → HTTP Request Defaults
Server Name or IP:
example.comPort:
443Protocol:
https
Совет: Используйте HTTP Request Defaults, чтобы менять сервер в одном месте (например, для переключения между staging и production).
Шаг 3: Добавить HTTP Request Sampler
ПКМ на Thread Group → Add → Sampler → HTTP Request
Name: Home Page
Method: GET
Path: /
Шаг 4: Добавить Cookie Manager
Для веб-тестирования обязательно — иначе JMeter будет игнорировать cookies.
ПКМ на Thread Group → Add → Config Element → HTTP Cookie Manager
Шаг 5: Добавить Listener
ПКМ на Thread Group → Add → Listener → View Results Tree
Также полезны:
Summary Report: Агрегированная статистика
Aggregate Report: Детальная статистика с перцентилями
Graph Results: Визуализация
Шаг 6: Запустить тест
Run → Start или зелёная кнопка ▶️
⚠️ Важно: Для реальных нагрузочных тестов используйте CLI-режим, не GUI!jmeter -n -t test.jmx -l results.jtl -e -o report/
GUI потребляет много ресурсов и искажает результаты.
Пример структуры теста
Test Plan
├── Thread Group (100 users, 60s ramp-up)
│ ├── HTTP Request Defaults (example.com)
│ ├── HTTP Cookie Manager
│ ├── HTTP Request: Home Page (GET /)
│ ├── HTTP Request: Login (POST /api/login)
│ ├── HTTP Request: Dashboard (GET /dashboard)
│ ├── Response Assertion (check status 200)
│ ├── Duration Assertion (< 2000ms)
│ └── Constant Timer (1000ms think time)
├── View Results Tree
└── Summary Report
6. JMeter: Assertions
Response Assertion
Проверяет содержимое ответа сервера. Самый часто используемый тип assertion.
| Поле | Варианты |
|---|---|
Field to Test | Text Response, Response Code, Response Headers, Document |
Pattern Matching | Contains, Matches, Equals, Substring, Not |
Пример: проверить, что ответ содержит «Welcome»
Field to Test: Text Response
Pattern Matching Rules: Contains
Patterns to Test: Welcome
Duration Assertion
Проверяет, что время ответа не превышает заданное значение. Идеально для валидации SLA.
Duration in milliseconds: 2000
Если запрос занимает больше 2 секунд — помечается как failed.
Факт: Duration Assertion практически не влияет на производительность теста, так как JMeter уже измеряет response time — assertion просто сравнивает с заданным значением.
JSON Assertion
Для API-тестирования: проверка значений в JSON-ответе.
Assert JSON Path exists: $.data.user.id
Expected Value: 12345
7. Gatling: быстрый старт
Установка
Требования: Java 8+ или Java 11+
Скачать: gatling.io
Распаковать архив
Или: Создать Maven/Gradle проект с Gatling plugin
Структура проекта
gatling-project/
├── src/
│ └── test/
│ ├── scala/
│ │ └── simulations/
│ │ └── MyFirstSimulation.scala
│ └── resources/
│ └── data/
│ └── users.csv
├── pom.xml (или build.gradle)
└── gatling.conf
Первый тест на Scala
package simulations
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class MyFirstSimulation extends Simulation {
// HTTP Configuration
val httpProtocol = http
.baseUrl("https://example.com")
.acceptHeader("application/json")
.userAgentHeader("Gatling")
// Scenario
val scn = scenario("Basic Load Test")
.exec(
http("Home Page")
.get("/")
.check(status.is(200))
)
.pause(1) // Think time: 1 second
.exec(
http("API Request")
.get("/api/data")
.check(status.is(200))
.check(jsonPath("$.status").is("ok"))
)
// Load Profile
setUp(
scn.inject(
rampUsers(100).during(60.seconds) // 100 users over 60 seconds
)
).protocols(httpProtocol)
}
Ключевые концепции Gatling
| Концепция | Описание |
|---|---|
Simulation | Класс теста, наследует Simulation |
Scenario | Сценарий поведения пользователя |
HTTP Protocol | Настройки HTTP (base URL, headers) |
Injection Profile | Как пользователи появляются (ramp, constant, etc.) |
Checks | Проверки ответа (аналог assertions) |
Feeders | Источники тестовых данных (CSV, JSON) |
Injection Profiles
// Постепенный рост
rampUsers(100).during(60.seconds)
// Константная нагрузка
constantUsersPerSec(10).during(5.minutes)
// Пиковая нагрузка (spike)
atOnceUsers(1000)
// Комбинация
setUp(
scn.inject(
nothingFor(5.seconds),
atOnceUsers(10),
rampUsers(100).during(60.seconds),
constantUsersPerSec(20).during(10.minutes)
)
)
Запуск теста
Через shell script:
bin/gatling.shЧерез Maven:
mvn clean gatling:testЧерез Gradle:
gradle gatlingRunОтчёты Gatling
Gatling генерирует красивые HTML-отчёты автоматически:
Global statistics (min/max/mean/percentiles)
Response time distribution
Active users over time
Requests per second
Response time percentiles over time
8. Gatling: продвинутые возможности
Feeders (Тестовые данные)
// CSV Feeder
val csvFeeder = csv("users.csv").circular
val scn = scenario("Login Test")
.feed(csvFeeder)
.exec(
http("Login")
.post("/api/login")
.formParam("username", "${username}")
.formParam("password", "${password}")
)
Файл users.csv:
username,password
user1,pass1
user2,pass2
user3,pass3
Корреляция (извлечение данных)
val scn = scenario("Extract Token")
.exec(
http("Login")
.post("/api/login")
.body(StringBody("""{"user":"test","pass":"test"}"""))
.check(jsonPath("$.token").saveAs("authToken"))
)
.exec(
http("Protected Resource")
.get("/api/data")
.header("Authorization", "Bearer ${authToken}")
)
Assertions на уровне simulation
setUp(
scn.inject(rampUsers(100).during(60.seconds))
).protocols(httpProtocol)
.assertions(
global.responseTime.max.lt(5000), // Max < 5s
global.responseTime.percentile3.lt(2000), // P95 < 2s
global.successfulRequests.percent.gt(99) // Success > 99%
)
Если assertion не проходит — тест считается failed (полезно для CI/CD).
9. Другие инструменты: k6 и Locust
k6 (Grafana k6)
Современный инструмент от Grafana Labs. Тесты пишутся на JavaScript.
| Плюсы | Минусы |
|---|---|
| JavaScript — знакомый язык | Нет GUI |
| Отличная CI/CD интеграция | Меньше протоколов, чем JMeter |
| Низкое потребление ресурсов | Облачная версия платная |
| Встроенные метрики и визуализация |
// k6 пример
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
vus: 100,
duration: '60s',
};
export default function () {
const res = http.get('https://example.com/');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
Locust
Python-based инструмент с веб-интерфейсом для мониторинга.
| Плюсы | Минусы |
|---|---|
| Python — простой для освоения | Только HTTP (в основном) |
| Веб-интерфейс для мониторинга | Менее производительный, чем Gatling/k6 |
| Distributed testing из коробки | |
| Бесплатный и open source |
# Locust пример
from locust import HttpUser, task, between
class WebsiteUser(HttpUser):
wait_time = between(1, 3)
@task
def home_page(self):
self.client.get("/")
@task(3) # Weight: выполняется в 3 раза чаще
def api_call(self):
self.client.get("/api/data")
Сравнение современных инструментов
| Инструмент | Язык тестов | GUI | Производительность | CI/CD |
|---|---|---|---|---|
JMeter | GUI/XML | ✅ | Средняя | Через плагины |
Gatling | Scala/Java/Kotlin | ❌ | Высокая | Нативная |
k6 | JavaScript | ❌ | Высокая | Нативная |
Locust | Python | Web UI | Средняя | Хорошая |
10. CI/CD интеграция
Зачем интегрировать в пайплайн
Автоматическое обнаружение регрессий производительности
Performance gates: блокировка релиза при деградации
Исторические данные для трендов
Shift-left: раннее обнаружение проблем
Факт: «Etsy использует Jenkins для автоматического запуска тестов и ловит 90% проблем производительности до продакшена.»
JMeter в Jenkins
pipeline {
agent any
stages {
stage('Performance Test') {
steps {
sh '''
jmeter -n -t tests/load-test.jmx \
-l results/results.jtl \
-e -o results/report/
'''
}
}
stage('Publish Results') {
steps {
perfReport sourceDataFiles: 'results/results.jtl'
}
}
}
post {
always {
archiveArtifacts artifacts: 'results/**'
}
}
}
Gatling в Jenkins
pipeline {
agent any
stages {
stage('Performance Test') {
steps {
sh 'mvn clean gatling:test'
}
}
}
post {
always {
gatlingArchive()
}
}
}
Performance Gates
Автоматическая проверка SLA и блокировка релиза при нарушении:
// Gatling assertions для CI/CD
setUp(scn.inject(...))
.assertions(
global.responseTime.percentile3.lt(2000), // P95 < 2s
global.failedRequests.percent.lt(1) // Errors < 1%
)
Если assertions не проходят — Gatling возвращает non-zero exit code, и пайплайн падает.
11. Типичные ошибки начинающих
1. Отсутствие Think Time
❌ Ошибка: Запросы без пауз между ними
Реальные пользователи не кликают мгновенно. Без think time вы создаёте нереалистичную нагрузку и перегружаете систему больше, чем она будет нагружена в реальности.
Решение: Добавляйте паузы (1-5 секунд) между запросами:
// JMeter: Constant Timer = 2000ms
// Gatling:
.pause(2) // 2 секунды
.pause(1, 3) // случайно от 1 до 3 секунд
2. Тестирование слишком поздно
❌ Ошибка: Нагрузочное тестирование только перед релизом
Найденные проблемы сложно и дорого исправлять.
Решение: Начинайте с базовых тестов на ранних этапах. Интегрируйте в CI/CD.
3. Нереалистичные сценарии
| Ошибка | Решение |
|---|---|
| Все пользователи делают одно и то же | Разные сценарии с разным весом |
| Одни и те же тестовые данные | Feeders с реалистичными данными |
| Нет географического распределения | Distributed testing из разных регионов |
4. Перегрузка Load Generator
⚠️ Проблема: Слишком много пользователей на одной машине → bottleneck на стороне генератора, не сервера.
Решение:
Мониторьте CPU/память машины с JMeter/Gatling
Используйте distributed testing
JMeter: ~300-500 threads на машину
Gatling: значительно больше благодаря async
5. Игнорирование ошибок в скриптах
Если скрипт возвращает ошибки — результаты теста невалидны. Всегда проверяйте:
Response codes (200 vs 500)
Response body содержит ожидаемые данные
Транзакции реально выполняются (проверьте в БД)
6. Тестирование на неполных данных
Факт: «Запрос, который выполняется меньше 1 секунды на БД 10 ГБ, может занимать более 10 секунд на БД 100 ГБ.»
Решение: База данных в тестовой среде должна быть близка к продакшену по объёму.
7. Мониторинг только Response Time
Response time важен, но недостаточен. Мониторьте также:
CPU и память серверов
Database connections и query time
Network I/O
Очереди и кэши
12. Best Practices
Планирование теста
Определите цели: Какую нагрузку должна выдержать система?
Соберите требования: SLA, ожидаемое количество пользователей, критичные сценарии
Проанализируйте продакшен: Реальные паттерны использования, пиковые часы
Создайте реалистичные сценарии: Не один запрос, а user journey
Выполнение теста
✅ Используйте CLI-режим для реальных тестов (не GUI)
✅ Изолируйте тестовую среду от продакшена
✅ Начинайте с малой нагрузки, постепенно увеличивайте
✅ Записывайте baseline перед изменениями
✅ Повторяйте тесты для статистической значимости
Анализ результатов
✅ Смотрите на перцентили, не только средние
✅ Корреляция с серверными метриками
✅ Сравнение с baseline и предыдущими тестами
✅ Документируйте результаты и условия теста
Чек-лист перед тестом
☐ Тестовая среда изолирована и стабильна
☐ База данных наполнена реалистичными данными
☐ Сценарии соответствуют реальному использованию
☐ Think time добавлен
☐ Assertions настроены
☐ Мониторинг серверов включён
☐ Baseline зафиксирован
☐ Команда уведомлена о проведении теста
13. Матрица выбора инструмента
Вопросы для выбора
| Вопрос | JMeter | Gatling | k6 | Locust |
|---|---|---|---|---|
| Команда умеет программировать? | Не обязательно | Да (Scala) | Да (JS) | Да (Python) |
| Нужен GUI? | ✅ Есть | ❌ Нет | ❌ Нет | Web UI |
| Тестирование не-HTTP? | ✅ Много протоколов | Ограниченно | Ограниченно | ❌ В основном HTTP |
| Высокие нагрузки (10k+ users)? | Distributed | ✅ Эффективен | ✅ Эффективен | Distributed |
| CI/CD важен? | Плагины | ✅ Нативно | ✅ Нативно | ✅ Хорошо |
| Нужны красивые отчёты? | Плагины | ✅ Из коробки | CLI + Grafana | Базовые |
Рекомендации по ситуациям
| Ситуация | Рекомендация |
|---|---|
| QA без опыта программирования | 🟢 JMeter |
| Команда разработчиков | 🟢 Gatling или k6 |
| Python-команда | 🟢 Locust |
| JavaScript-команда | 🟢 k6 |
| Enterprise с разными протоколами | 🟢 JMeter |
| Микросервисы и API | 🟢 Gatling или k6 |
| CI/CD-first подход | 🟢 Gatling или k6 |
| Ограниченные ресурсы машин | 🟢 Gatling (async) |
14. Пример сквозного теста
Сценарий: E-commerce checkout
Типичный сценарий для интернет-магазина:
Открыть главную страницу
Поиск товара
Просмотр товара
Добавление в корзину
Переход в корзину
Оформление заказа
JMeter Test Plan (структура)
Test Plan: E-commerce Load Test
├── Thread Group (200 users, 120s ramp-up, 10 min duration)
│ ├── HTTP Request Defaults
│ │ └── Server: shop.example.com
│ ├── HTTP Cookie Manager
│ ├── CSV Data Set Config (products.csv)
│ │
│ ├── Transaction Controller: Browse
│ │ ├── HTTP Request: Home Page (GET /)
│ │ ├── Gaussian Random Timer (1000-3000ms)
│ │ ├── HTTP Request: Search (GET /search?q=${product})
│ │ └── Gaussian Random Timer (2000-4000ms)
│ │
│ ├── Transaction Controller: View Product
│ │ ├── HTTP Request: Product Page (GET /product/${productId})
│ │ └── Gaussian Random Timer (3000-5000ms)
│ │
│ ├── Transaction Controller: Add to Cart
│ │ ├── HTTP Request: Add to Cart (POST /cart/add)
│ │ └── Gaussian Random Timer (1000-2000ms)
│ │
│ ├── Transaction Controller: Checkout
│ │ ├── HTTP Request: View Cart (GET /cart)
│ │ ├── HTTP Request: Checkout (POST /checkout)
│ │ └── Response Assertion: Order Confirmed
│ │
│ ├── Duration Assertion: All requests < 3000ms
│ │
├── Aggregate Report
└── HTML Report (Dashboard)
Gatling Simulation
class EcommerceSimulation extends Simulation {
val httpProtocol = http
.baseUrl("https://shop.example.com")
.acceptHeader("text/html,application/json")
val productFeeder = csv("products.csv").random
val browse = exec(
http("Home Page").get("/").check(status.is(200))
).pause(1, 3)
.feed(productFeeder)
.exec(
http("Search").get("/search?q=${product}").check(status.is(200))
).pause(2, 4)
val viewProduct = exec(
http("Product Page")
.get("/product/${productId}")
.check(status.is(200))
.check(css("button.add-to-cart").exists)
).pause(3, 5)
val addToCart = exec(
http("Add to Cart")
.post("/cart/add")
.formParam("productId", "${productId}")
.check(status.is(200))
).pause(1, 2)
val checkout = exec(
http("View Cart").get("/cart").check(status.is(200))
).pause(2)
.exec(
http("Checkout")
.post("/checkout")
.check(status.is(200))
.check(substring("Order Confirmed"))
)
val scn = scenario("E-commerce Flow")
.exec(browse, viewProduct, addToCart, checkout)
setUp(
scn.inject(
rampUsers(200).during(120.seconds),
constantUsersPerSec(2).during(10.minutes)
)
).protocols(httpProtocol)
.assertions(
global.responseTime.percentile3.lt(3000),
global.successfulRequests.percent.gt(99)
)
}
Итоги
Нагрузочное тестирование — не роскошь, а необходимость. Узнать о проблемах производительности до пользователей — в разы дешевле и проще, чем разбираться с инцидентами на продакшене.
Ключевые выводы:
JMeter — для команд без опыта программирования, широкого спектра протоколов, богатой экосистемы плагинов
Gatling — для разработчиков, высоких нагрузок, CI/CD интеграции, красивых отчётов
k6 — для JavaScript-команд, DevOps-культуры, современных API
Locust — для Python-команд, простых сценариев
Важные принципы:
Смотрите на перцентили (P95, P99), не средние
Добавляйте think time между запросами
Используйте реалистичные сценарии и данные
Интегрируйте в CI/CD с performance gates
Тестируйте рано и часто, не только перед релизом
Мониторьте не только response time, но и серверные метрики
Формула успешного нагрузочного тестирования:
Реалистичные сценарии + Правильные метрики + Регулярность + CI/CD интеграция = Уверенность в производительности
Начните с простого: установите JMeter или Gatling, создайте тест на один endpoint, запустите с 10 пользователями. Затем усложняйте: добавляйте сценарии, увеличивайте нагрузку, интегрируйте в пайплайн. Главное — начать.
А лучшие вакансии для QA (тестировщиков) ищите на hirehi.ru