Нагрузочному тестированию
Определений много...
На википедии:
процесс систематического анализа и проверки программного продукта на соответствие нефункциональным требованиям путём подачи предопределенной нагрузки с использованием инструментов нагрузочного тестирования.
Но это больше похоже на Performance Engineering.
На практике часто под нагрузочным тестированием имеют ввиду тест, который собирает аналитику по скорости ответов на запросы в мультипользовательском приложении.
Правда не во всех типах приложений есть пользователи.
По сути речь идет о степени конкуррентности запросов с разным контекстом.
Тестирование производительности
Делится на большое количество типов.
Некоторые из них:
Здесь хорошо написано про теорию тестирования.
Инструменты нагрузочного тестирования
Типичные open-source инструменты для генерации нагрузки и анализа:
Это все?
Конечно, нет.
Есть статья, которая немного субъективна в плане k6, но обзор не плохой.
Список оттуда:
  • ApacheBench
  • Artillery
  • Drill
  • Gatling
  • Hey
  • JMeter
  • k6
  • Locust
  • Siege
  • Tsung
  • Vegeta
  • Wrk
Этот список тоже неполный. Есть так же огромное количество коммерческих инструментов.
Здесь можно отметить Drill, потому что он написан на Rust, но разработка устала.
А также Hue и Vegeta, потому что это чисто CLI-инструменты безскриптовые. Такие удобно иметь под рукой, чтобы быстро проверить живость какого-нибудь сервера.
Профилировщики Java
Нагрузочное тестирование можно использовать, чтобы находить узкие места. Cначала включить профилировщик на сервере, потом пустить на него нагрузку, посмотреть, что в данных.
Профилировщики:
  1. async-profiler
  2. Alibaba Arthas
  3. MyPerf4j
  4. VisualVM
  5. JFR
Результаты часто визуализируют в FlameGraph'ах. Но на том же сайте есть примеры других визуализаций, например, HeatMaps. Flamegraphs хорошо работают в простых приложениях. Для анализа задержек приложений и их причин лучше работают frequency trails. HeatMaps удобно использовать для анализа нагрузки по времени, а так же для анализа нагрузки нескольких процессов на сервере.

В последних версиях Java (>=11), можно собирать события JFR.
Как увидеть поддерживаемые события:
#JDK 11-16:
java -XX:StartFlightRecording:filename=m.jfr -version $ jfr metadata m.jfr.
# JDK 17, and later:
jfr metadata 
Узкие места
По времени
  • Время выполнения метода за вызов.
  • Суммарное время выполнение метода за период профилирования.

Почему-то часто не обращают внимание, когда метод выполняется быстро, но вызывается миллион раз. И по суммарному времени выполнения метода в программе, метод находится в топе. Оба подхода имеют место быть.

По счетчикам
async-profiler умеет мерить:
./profiler.sh list 999

Basic events:
  cpu
  alloc
  lock
  wall
  itimer
Java method calls:
  ClassName.methodName
Perf events:
  page-faults
  context-switches
  cycles
  instructions
  cache-references
  cache-misses
  branches
  branch-misses
  bus-cycles
  L1-dcache-load-misses
  LLC-load-misses
  dTLB-load-misses
  mem:breakpoint
  trace:tracepoint
Apache Jmeter
Don't use GUI mode for load testing !, only for Test creation and Test debugging.
For load testing, use CLI Mode (was NON GUI):
   jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
& increase Java Heap to meet your test requirements:
   Modify current env variable HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" in the jmeter batch file
Check : https://jmeter.apache.org/usermanual/best-practices.html
Особенности JMeter
  1. UI можно использовать для дизайна теста, а для реальной проверки надо запускать его в режиме CLI.
  2. View Result Tree, и все листенеры, которые собирают данные, очень тяжелые, их надо удалять в реальном тесте. Результаты все равно можно будет собирать.
  3. Результаты надо писать в CSV. По умолчанию XML, но XML тяжелый вариант.
  4. Расчет шага нагрузки.
  5. Экспорт в Clickhouse.
Много всякого: https://github.com/aliesbelik/awesome-jmeter
Рекомендуемые настройки
(добавить в path_to_jmeter/bin/user.properties)
jmeter.save.saveservice.output_format=csv
jmeter.save.saveservice.data_type=false
jmeter.save.saveservice.label=true
jmeter.save.saveservice.response_code=true
jmeter.save.saveservice.response_data.on_error=false
jmeter.save.saveservice.response_message=false
jmeter.save.saveservice.assertion_results_failure_message=false
jmeter.save.saveservice.successful=true
jmeter.save.saveservice.thread_name=true
jmeter.save.saveservice.time=true
jmeter.save.saveservice.subresults=false
jmeter.save.saveservice.assertions=true
jmeter.save.saveservice.latency=true
jmeter.save.saveservice.bytes=true
jmeter.save.saveservice.hostname=true
# This will enable correct graphs display 
# which deal with threads after reloading the results file.
jmeter.save.saveservice.thread_counts=true
jmeter.save.saveservice.sample_count=true
jmeter.save.saveservice.timestamp_format=HH:mm:ss
jmeter.save.saveservice.default_delimiter=;
jmeter.save.saveservice.print_field_names=true
# This is needed to ensure all results are 
# available when Listener runs
jmeter.save.saveservice.autoflush=true
Авторские курсы