惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
腾讯CDC
爱范儿
爱范儿
Google DeepMind News
Google DeepMind News
V
V2EX
Blog — PlanetScale
Blog — PlanetScale
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
量子位
F
Fortinet All Blogs
G
Google Developers Blog
T
The Blog of Author Tim Ferriss
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
T
Tailwind CSS Blog
J
Java Code Geeks
S
SegmentFault 最新的问题
D
Docker
博客园 - 司徒正美
The GitHub Blog
The GitHub Blog
Jina AI
Jina AI
M
MIT News - Artificial intelligence
博客园 - 【当耐特】

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания
Нагрузочное тестирование с Apache JMeter: Best Practices
sproshchaev · 2026-04-23 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение8 мин

Охват и читатели1.2K

Туториал

Введение

Всем привет, меня зовут Сергей Прощаев. Я Tech Lead и руководитель направления Java | Kotlin разработки в FinTech, а также преподаю на курсах разработки и архитектуры в OTUS. В этой статье я расскажу не просто про кнопки в Apache JMeter, а про то, как перестать играть в нагрузочное тестирование и начать получать от него реальную пользу, которая спасает нервы в ночь релиза.

Видел много отчетов о нагрузочном тестировании. Знаете, что их объединяет в 80% случаев? Они рисуют красивые графики роста трафика и пишут «Система стабильна, ограничение — БД». На этом всё. А через неделю после релиза прод падает в час пик, потому что никто не проверил, как поведет себя кэш при 100% заполнении хипа или как работает пул соединений, когда один из инстансов сервиса начинает тупить.

В статье постараюсь разобрать это направление тестирования по шагам. Без воды, с Best Practice, которые используют команды, отвечающие за реальный Highload. А в конце — расскажу про открытый урок, где мы закрепим это всё на практике, чтобы вы не учились на своих дорогих ошибках.

Знакомство с Apache JMeter: Почему он, а не модный Gatling?

Часто можно услышать от новичков: «JMeter — это же прошлый век, UI некрасивый, Java‑стек, давай лучше Gatling, там кодом, это стильно, модно, молодежно». Доля правды в этом есть, но это взгляд разработчика, который хочет писать скрипты как код. Взгляд системного аналитика или инженера по нагрузке немного другой.

JMeter выигрывает не красотой, а инструментальной гибкостью и порогом входа для команды.

  1. Протоколы. Помимо HTTP(S), он из коробки тянет JDBC, Kafka, JMS, gRPC (через плагины). Вам не нужно собирать отдельный проект на Scala, чтобы долбиться в базу данных прямыми запросами или проверить очередь сообщений.

  2. Визуализация для «соседа». Когда вам нужно показать тестировщику, как именно мы парсим CSRF‑токен из страницы, открыть.jmx файл в UI куда проще, чем объяснять регулярки в коде.

  3. Экосистема. Плагин JMeter Plugins Manager дает готовые графики процентилей и затупы потоков без необходимости писать экспортеры в Prometheus.

Конечно, у него есть недостатки — он прожорлив по памяти при отрисовке больших графиков в GUI. Но сильные инженеры знают правило: GUI — только для отладки. Нагрузку гоняем исключительно в CLI‑режиме. И дальше я покажу, как это работает.

Создание и отладка HTTPS‑скрипта: главная ловушка

Самая частая ловушка при создании скрипта — запись через HTTP(S) Test Script Recorder. Вы нажимаете кнопку Start, проходите сценарий в браузере, и... получаете гору запросов к google-analytics.comfonts.gstatic.com и прочему мусору. А главное — получаете жестко зашитые ID сессий или токены, которые на втором запуске превращают тест в тыкву.

Мой подход к созданию чистого скрипта (Best Practice):

  1. Transaction Controller. Каждый бизнес‑шаг (Логин, Поиск, Оплата) — отдельный контроллер. Это дает нам время отклика именно бизнес‑операции, а не кучки из 50 ресурсов.

  2. HTTP Header Manager. Никогда не ленитесь его настраивать. Без корректного Accept-Encoding: gzip вы будете грузить сеть и получать завышенное время ответа на статике.

  3. Регулярки и JSON Extractor. Вот где собака зарыта. Почти любое современное приложение шлет в ответе authenticity_tokenrequestVerificationToken или SessionId в куках.

Приведу простой пример обработки ответа в JMeter. Допустим, после логина сервер возвращает JSON с токеном, который нужно вставить в заголовок X-Auth-Token для всех следующих запросов.

// Это не код Java для выполнения, это пример настройки компонента JSR223 PostProcessor (Groovy)
// Я предпочитаю Groovy, он шустрее BeanShell и меньше утилизирует CPU

import groovy.json.JsonSlurper;

def response = prev.getResponseDataAsString();
def json = new JsonSlurper().parseText(response);
def token = json.data.authToken;

// Кладем токен в переменные JMeter
vars.put("AUTH_TOKEN", token);

// Логируем, чтобы при отладке не гадать — вытащилось или нет
log.info("Token extracted: " + token);

Почему это важно? В одном из проектов коллеги жаловались, что JMeter «глючит» — мол, проходит только один пользователь из десяти. Оказалось, что при разборе ответа через стандартный Boundary Extractor (по левой и правой границе) в ответе внезапно появлялся пробел в JSON из‑за особенностей форматирования бэкенда.

Регулярка "authToken":"(.*?)"ломалась, и 90% запросов шли без токена, получая 403. Деталь, которая стоила нескольких часов дебага. Поэтому — только JSON Extractor или Groovy.

Проведение нагрузочного теста: думаем как прод

Включать нагрузку с ноутбука через Wi‑Fi в кафе — это не совсем про тестирование (хотя почему и нет). Чтобы увидеть реальное поведение системы, нужно соблюсти несколько суровых правил.

Распределенный тест (Master‑Slave).Одна машина с Windows/Mac (мастер) управляет, несколько голых Linux‑серверов (слейвы) генерируют трафик. Почему Linux? Потому что там почти нет ограничений на количество ephemeral ports по умолчанию (они есть, но легче тюнятся через sysctl), по сравнению с Windows, и сетевая подсистема работает стабильнее.

Рис. 1 Архитектура распределенного нагрузочного тестирования с Apache JMeter

Рис. 1 Архитектура распределенного нагрузочного тестирования с Apache JMeter

На схеме показана классическая архитектура распределённого нагрузочного тестирования. С рабочего места инженера (ноутбук или десктоп) запускается Мастер JMeter — это управляющий узел, который содержит сценарий теста и раздаёт команды. Сам он трафик не генерирует. Реальную нагрузку создают Slave‑узлы — один или несколько выделенных серверов, обычно под Linux. Мастер синхронизирует их запуск и собирает агрегированные результаты.

Параллельно со стендом нагрузки работает мониторинг хоста (CPU, RAM, сеть), данные с которого также стекаются мастеру для последующей корреляции с временами отклика. Сами Slave‑узлы отправляют HTTPS‑запросы на целевой сервис, расположенный за балансировщиком. А тот, в свою очередь, взаимодействует с базой данных или кэшем. Такой подход позволяет не только проверить производительность приложения, но и увидеть, где именно находится узкое место: в самом приложении, на сетевом уровне или в инфраструктуре данных.

Профиль нагрузки — это не прямая линия вверх.
В реальной жизни нагрузка похожа на морские волны. Я всегда использую несколько плагинов:

  • Concurrency Thread Group (вместо стандартной) для удобного управления временем выхода на плато.

  • Throughput Shaping Timer — чтобы эмулировать не просто «100 потоков», а именно «500 запросов в секунду». Это критично для тестирования брокеров сообщений или API Gateway, которые могут начать шейпить трафик.

Анализ результатов: почему Average вводит в заблуждение?

Самое странное, что можно сделать — это открыть Summary Report и посмотреть в столбец Average (Среднее время).

Я видел отчеты, где писали: «Среднее время ответа 120 мс, всё хорошо». Потом выяснялось, что 99% запросов отрабатывали за 30 мс, а оставшийся 1% — за 12 000 мс (12 секунд!). Из‑за усреднения эти 12 секунд превратились в «приемлемые 120 мс». Пользователи при этом плевались и слали гневные тикеты.

На что можно полагаться:

  1. Response Time Graph по процентилям (через плагин jp@gc). Нас интересует p90, p95, p99. Если p90 = 30 мс, а p99 = 5 секунд — у нас проблема с долгим хвостом (GC pause или реконнект к БД).

  2. Transactions per Second (TPS). Ищем точку насыщения. Момент, когда добавляем виртуальных пользователей, а количество обработанных запросов в секунду перестает расти или падает — это и есть предел производительности текущего железа/конфигурации.

  3. Latency vs Connect Time. Если Connect Time высокий, проблема на сетевом уровне или в рукопожатии TLS. Если Latency высокая при низком Connect Time — копаем приложение.

Генерация HTML‑отчётов: зачем платить за BlazeMeter?

Многие до сих пор делают скриншоты графиков из GUI или, что еще хуже, пытаются рисовать графики в Excel, экспортируя сырой .jtl. Хотя в JMeter уже несколько лет есть штатная фича генерации Dashboard Report.

После прогона теста в CLI у вас есть .jtl файл. Даже если он весит 10 ГБ (что бывает), одной командой вы получаете полноценный дашборд, который не стыдно отправить заказчику:

jmeter -g /path/to/result.jtl -o /path/to/report/folder

Открываете index.html и видите:

  • APDEX (индекс удовлетворенности пользователей).

  • Тепловую карту времени отклика.

  • Топ ошибок по кодам ответа.

Совет: Если отчет кажется вам скучным, поднимите флаг jmeter.reportgenerator.overall_granularity=1000 в user.properties, чтобы сгладить пиковые выбросы на графиках и сделать картину чище.

Историческая справка: Как NASA «уронило» марсоход из‑за отсутствия нагрузочного теста

Марсоход Spirit попал в петлю перезагрузок из‑за проблемы с флэш‑памятью

В январе 2004 года, через 18 солов после посадки на Марс, марсоход NASA Spirit перестал нормально отвечать на команды и попал в бесконечную петлю перезагрузок.

Инженеры выяснили, что причина — в файловой системе флэш‑памяти (256 МБ). Из‑за большого количества накопившихся файлов (включая служебные логи, данные калибровки и другие записи, частично накопленные ещё во время перелёта) при попытке смонтировать файловую систему или работать с ней расходовалось слишком много оперативной памяти (RAM). Это приводило к ошибке, перезагрузке и повторению цикла.

Почему это произошло? На Земле тестирование проводилось в «тепличных» условиях и в основном проверяло функциональность. Никто не смоделировал реальную длительную эксплуатацию с накоплением сотен и тысяч файлов при ограниченных ресурсах. Когда ровер начал активно работать — создавать новые файлы во время сеансов связи, движения и научных измерений, — проявился недостаток robustness (устойчивости) файловой системы.

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

NASA удалось спасти миссию: ровер перевели в «crippled mode» (работа без использования флэш‑памяти), удалили тысячи ненужных файлов, а позже полностью переформатировали флэш. После этого Spirit продолжил работу и в итоге проработал более 6 лет (до 2010 года).

Урок для тестирования

Эта история отлично иллюстрирует цену нагрузочного и стресс‑тестирования. Один короткий сеанс связи — всё работает. Тысячи операций с накоплением логов и файлов в условиях ограниченной RAM и флэш — система падает в петлю.

Инструменты вроде JMeter или специализированных тестов для embedded‑систем помогают заранее выявлять такие boundary‑кейсы: длительную нагрузку записи/чтения, рост количества файлов, утечки ресурсов и поведение при приближении к пределам памяти.

Заключение: нагрузочное тестирование — это не QA, это инженерия хаоса

Разбор работы с JMeter — это не заучивание горячих клавиш. Это тренировка системного мышления. Умение спроектировать профиль нагрузки, вытащить токен, понять процентиль и объяснить разработчикам, почему их «оптимизация» запроса привела к росту времени ответа в хвосте.

Плохой специалист нажимает зеленую кнопку Play и смотрит на среднее время. Хороший — строит распределенный кластер, имитирует смешанную нагрузку и находит узкое место за неделю до релиза, а не в 3 часа ночи после него.

Если этот разбор показался вам полезным и вы хотите разобраться в практиках команд, которые держат многомиллионный RPS, приглашаю вас на открытые уроки курса «Нагрузочное тестирование» в OTUS. На уроках мы научимся работать с JMeter, разберем типовые ошибки при анализе .jtl логов и заложим фундамент, чтобы вы могли уверенно отвечать на вопросы о производительности на собеседованиях.

28 апреля в 20:00 — «Первый нагрузочный тест в Apache JMeter». Записаться

19 мая в 20:00 — «Навыки нагрузочного тестирования и их роль в развитии инженера». Записаться

Уроки бесплатные, нужно только зарегистрироваться.