Перейти к основному содержимому

Gatling vs JMeter vs The Grinder: сравнение инструментов нагрузочного тестирования

· 8 мин. чтения

1. Введение

Выбор правильного инструмента для работы может быть сложной задачей. В этом руководстве мы упростим это, сравнив три инструмента нагрузочного тестирования веб-приложений — Apache JMeter, Gatling и The Grinder — с простым REST API.

2. Инструменты нагрузочного тестирования

Во-первых, давайте быстро рассмотрим некоторые предыстории каждого из них.

2.1. Гатлинг

Gatling — это инструмент нагрузочного тестирования, который создает тестовые сценарии в Scala. Рекордер Gatling генерирует тестовые сценарии Scala, что является ключевой функцией Gatling. Ознакомьтесь с нашим руководством « Введение в Gatling » для получения дополнительной информации.

2.2. JMeter

JMeter — это инструмент нагрузочного тестирования от Apache. Он предоставляет приятный графический интерфейс, который мы можем использовать для настройки. Уникальная функция, называемая логическими контроллерами, обеспечивает большую гибкость при настройке тестов в графическом интерфейсе.

Посетите наш учебник « Введение в JMeter», чтобы получить скриншоты и дополнительные пояснения.

2.3. Измельчитель

И наш последний инструмент, The Grinder , предоставляет скриптовый движок, более основанный на программировании, чем два других, и использует Jython. Однако в The Grinder 3 есть функция записи сценариев.

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

3. Настройка тестового примера

Далее, для нашего теста нам понадобится API. Наш функционал API включает в себя:

  • добавить/обновить запись о наградах
  • просмотреть одну/все записи о наградах
  • связать транзакцию с записью вознаграждения клиента
  • просмотр транзакций для записи вознаграждений клиентов

Наш сценарий:

В магазине проводится общенациональная распродажа с новыми и постоянными покупателями, которым нужны учетные записи для поощрения клиентов, чтобы сэкономить. API вознаграждений проверяет учетную запись вознаграждения клиента по идентификатору клиента . Если учетная запись для вознаграждений не существует, добавьте ее, а затем свяжите с транзакцией.

После этого мы запрашиваем транзакции.

3.1. Наш REST API

Давайте кратко рассмотрим API, просмотрев некоторые заглушки методов:

@PostMapping(path="/rewards/add")
public @ResponseBody RewardsAccount addRewardsAcount(@RequestBody RewardsAccount body)

@GetMapping(path="/rewards/find/{customerId}")
public @ResponseBody Optional<RewardsAccount> findCustomer(@PathVariable Integer customerId)

@PostMapping(path="/transactions/add")
public @ResponseBody Transaction addTransaction(@RequestBody Transaction transaction)

@GetMapping(path="/transactions/findAll/{rewardId}")
public @ResponseBody Iterable<Transaction> findTransactions(@PathVariable Integer rewardId)

Обратите внимание на некоторые отношения, такие как запрос транзакций по идентификатору вознаграждения и получение учетной записи вознаграждения по идентификатору клиента . Эти отношения вызывают некоторую логику и некоторый анализ ответов для создания нашего тестового сценария.

Тестируемое приложение также использует базу данных H2 в памяти для обеспечения устойчивости.

К счастью, все наши инструменты справляются с этим довольно хорошо, некоторые лучше, чем другие.

3.2. Наш план тестирования

Далее нам понадобятся тестовые скрипты.

Чтобы получить справедливое сравнение, мы выполним одинаковые шаги автоматизации для каждого инструмента:

  1. Создание случайных идентификаторов учетных записей клиентов
  2. Разместить транзакцию
  3. Проанализируйте ответ для случайного идентификатора клиента и идентификатора транзакции.
  4. Запрос идентификатора учетной записи вознаграждения клиента с идентификатором клиента
  5. Разобрать ответ для идентификатора учетной записи вознаграждения
  6. Если идентификатор учетной записи вознаграждения не существует, добавьте его с сообщением
  7. Опубликуйте ту же первоначальную транзакцию с обновленным идентификатором вознаграждения, используя идентификатор транзакции.
  8. Запрос всех транзакций по идентификатору учетной записи вознаграждения

Давайте подробнее рассмотрим шаг 4 для каждого инструмента. И обязательно ознакомьтесь с образцом для всех трех завершенных сценариев .

3.3. Гатлинг

Для Gatling знакомство со Scala является преимуществом для разработчиков, поскольку Gatling API надежен и содержит множество функций.

API Гатлинга использует подход DSL-строителя, как мы можем видеть на шаге 4:

.exec(http("get_reward")
.get("/rewards/find/${custId}")
.check(jsonPath("$.id").saveAs("rwdId")))

Особо следует отметить поддержку Gatling пути JSON, когда нам нужно прочитать и проверить ответ HTTP. Здесь мы возьмем идентификатор награды и сохраним его во внутреннем состоянии Гатлинга.

Кроме того, язык выражений Гатлинга упрощает динамические строки тела запроса:

.body(StringBody(
"""{
"customerRewardsId":"${rwdId}",
"customerId":"${custId}",
"transactionDate":"${txtDate}"
}""")).asJson)

Наконец, наша конфигурация для этого сравнения. 1000 прогонов задаются как повторение всего сценария, метод atOnceUsers устанавливает потоки/пользователей:

val scn = scenario("RewardsScenario")
.repeat(1000) {
...
}
setUp(
scn.inject(atOnceUsers(100))
).protocols(httpProtocol)

Весь скрипт Scala доступен для просмотра в нашем репозитории Github.

3.4. JMeter

JMeter генерирует файл XML после настройки графического интерфейса. Файл содержит определенные объекты JMeter с заданными свойствами и их значениями, например:

<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Transaction" enabled="true">
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Transaction Id Extractor" enabled="true">

Проверьте атрибуты testname , они могут быть помечены, поскольку мы распознаем их в соответствии с логическими шагами, описанными выше. Возможность добавлять дочерние элементы, переменные и шаги зависимостей дает JMeter гибкость, которую обеспечивают сценарии. Кроме того, мы даже устанавливаем область действия для наших переменных!

Наша конфигурация для прогонов и пользователей в JMeter использует ThreadGroups :

<stringProp name="ThreadGroup.num_threads">100</stringProp>

Просмотрите весь файл jmx в качестве ссылки . Хотя это и возможно, написание тестов в формате XML в виде файлов .jmx не имеет смысла с полнофункциональным графическим интерфейсом.

3.5. Измельчитель

Без функционального программирования Scala и графического интерфейса наш Jython-скрипт для The Grinder выглядит довольно просто. Добавьте несколько системных классов Java, и у нас будет намного меньше строк кода.

customerId = str(random.nextInt());
result = request1.POST("http://localhost:8080/transactions/add",
"{"'"customerRewardsId"'":null,"'"customerId"'":"+ customerId + ","'"transactionDate"'":null}")
txnId = parseJsonString(result.getText(), "id")

Однако меньшее количество строк кода настройки теста уравновешивается потребностью в большем количестве кода обслуживания строк, такого как анализ строк JSON. Кроме того, API HTTPRequest ограничен по функциональности.

С The Grinder мы определяем потоки, процессы и запускаем значения во внешнем файле свойств:

grinder.threads = 100
grinder.processes = 1
grinder.runs = 1000

Наш полный Jython-скрипт для The Grinder будет выглядеть так .

4. Тестовые прогоны

4.1. Выполнение теста

Все три инструмента рекомендуют использовать командную строку для тестов с большой нагрузкой.

Для запуска тестов мы будем использовать Gatling версии 3.4.0 с открытым исходным кодом в качестве отдельного инструмента, JMeter 5.3 и The Grinder версии 3 .

Gatling требует только, чтобы у нас были установлены JAVA_HOME и GATLING_HOME . Для выполнения Gatling используем:

./gatling.sh

в каталоге GATLING_HOME/bin.

JMeter нужен параметр, чтобы отключить графический интерфейс для теста, как было предложено при запуске графического интерфейса для настройки:

./jmeter.sh -n -t TestPlan.jmx -l log.jtl

Как и Gatling, Grinder требует, чтобы мы установили JAVA_HOME и GRINDERPATH . Однако ему нужны еще несколько свойств:

export CLASSPATH=/home/lore/Documents/grinder-3/lib/grinder.jar:$CLASSPATH
export GRINDERPROPERTIES=/home/lore/Documents/grinder-3/examples/grinder.properties

Как упоминалось выше, мы предоставляем файлgrinder.properties для дополнительной настройки, такой как потоки, запуски, процессы и хосты консоли.

Наконец, мы загружаем консоль и агенты с помощью:

java -classpath $CLASSPATH net.grinder.Console
java -classpath $CLASSPATH net.grinder.Grinder $GRINDERPROPERTIES

4.2. Результаты теста

Каждый из тестов выполнял 1000 прогонов со 100 пользователями/потоками. Давайте раскроем некоторые из основных моментов:

   |     | **Успешные запросы**    | **Ошибки**    | **Общее время тестирования (с)**    | **Среднее время отклика (мс)**    | ** Средняя пропускная способность**   | 
| **Гатлинг** | 500000 запросов | 0 | 218с | 42 | 2283 запроса/с |
| **JMeter** | 499997 запросов | 0 | 237 с | 46 | 2101 запросов/с |
| **Измельчитель** | 499997 запросов | 0 | 221с | 43 | 2280 запросов/с |

Результаты показывают, что 3 инструмента имеют одинаковую скорость, при этом Гатлинг немного опережает другие 2, исходя из средней пропускной способности.

Каждый инструмент также предоставляет дополнительную информацию в более удобном пользовательском интерфейсе.

В конце выполнения Gatling сгенерирует отчет в формате HTML, который содержит несколько графиков и статистических данных как для всего выполнения, так и для каждого запроса. Вот фрагмент отчета о результатах теста:

./9581e353aed0c397e1a71cd43d5c94ba.png

При использовании JMeter мы можем открыть графический интерфейс после запуска теста и создать отчет в формате HTML на основе файла журнала, в котором мы сохранили результаты:

./a00d2a8e376bcc3f45d81d8ecad7eef1.png

HTML-отчет JMeter также содержит разбивку статистики по запросам.

Наконец, консоль Grinder записывает статистику для каждого агента и запускает:

./eb8f64496cfdbc8e83c1e1e441409de2.png

Хотя Grinder является высокоскоростным, он достигается за счет дополнительного времени разработки и меньшего разнообразия выходных данных.

5. Резюме

Теперь пришло время бросить общий взгляд на каждый из инструментов нагрузочного тестирования.

   |     | **Гатлинг**    | **JMeter**    | **Измельчитель**   | 
| Проект и сообщество | 9 | 9 | 6 |
| Производительность | 9 | 8 | 9 |
| Скриптовость/API | 7 | 9 | 8 |
| интерфейс | 9 | 8 | 6 |
| отчеты | 9 | 7 | 6 |
| Интеграция | 7 | 9 | 7 |
| **Резюме** | **8.3** | **8.3** | **7** |

Гатлинг:

  • Надежный, отточенный инструмент для нагрузочного тестирования, который выводит красивые отчеты с помощью сценариев Scala.
  • Уровни поддержки Open Source и Enterprise для продукта

JMeter:

  • Надежный API (через графический интерфейс) для разработки тестовых сценариев без необходимости написания кода
  • Поддержка Apache Foundation и отличная интеграция с Maven

Измельчитель:

  • Инструмент быстрого нагрузочного тестирования для разработчиков, использующих Jython.
  • Масштабируемость между серверами обеспечивает еще больший потенциал для крупных тестов.

Проще говоря, если вам нужны скорость и масштабируемость, используйте The Grinder.

Если великолепно выглядящие интерактивные графики помогают показать прирост производительности в пользу изменений, тогда используйте Gatling.

JMeter — это инструмент для сложной бизнес-логики или уровня интеграции со многими типами сообщений. Являясь частью Apache Software Foundation, JMeter предоставляет зрелый продукт и большое сообщество.

6. Заключение

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

Наконец, API и скрипты можно найти на Github .