«1. Введение
Выбор правильного инструмента для работы может быть сложной задачей. В этом руководстве мы упростим это, сравнив три инструмента нагрузочного тестирования веб-приложений — Apache JMeter, Gatling и The Grinder — с простым REST API.
2. Инструменты нагрузочного тестирования
Во-первых, давайте быстро пробежимся по каждому из них.
2.1. Gatling
Gatling — это инструмент для нагрузочного тестирования, который создает тестовые сценарии в Scala. Рекордер Gatling генерирует тестовые сценарии Scala, что является ключевой функцией Gatling. Ознакомьтесь с нашим руководством «Введение в Gatling» для получения дополнительной информации.
2.2. JMeter
JMeter — это инструмент нагрузочного тестирования от Apache. Он предоставляет приятный графический интерфейс, который мы можем использовать для настройки. Уникальная функция, называемая логическими контроллерами, обеспечивает большую гибкость при настройке тестов в графическом интерфейсе.
Посетите наш учебник «Введение в JMeter», чтобы увидеть снимки экрана и дополнительные пояснения.
2.3. The Grinder
И наш последний инструмент, 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. Наш план тестирования
Далее нам нужны тестовые сценарии.
Чтобы получить справедливое сравнение, мы выполним одни и те же шаги автоматизации для каждого инструмента:
- Generate random customer account ids
- Post a transaction
- Parse the response for the random customer id and transaction id
- Query for a customer rewards account id with the customer id
- Parse the response for the rewards account id
- If no rewards account id exists then add one with a post
- Post the same initial transaction with updated rewards id using the transaction id
- Query for all transactions by rewards account id
Давайте подробнее рассмотрим шаг 4 для каждого инструмента. И обязательно ознакомьтесь с образцом для всех трех завершенных сценариев.
3.3. Gatling
Для Gatling знакомство со Scala является преимуществом для разработчиков, поскольку Gatling API надежен и содержит множество функций.
Gatling 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 гибкость, которую обеспечивают сценарии. Кроме того, мы даже устанавливаем область действия для наших переменных!
<stringProp name="ThreadGroup.num_threads">100</stringProp>
Наша конфигурация для прогонов и пользователей в JMeter использует ThreadGroups:
«
«Просмотрите весь файл jmx в качестве ссылки. Хотя это и возможно, написание тестов в формате XML в виде файлов .jmx не имеет смысла с полнофункциональным графическим интерфейсом.
customerId = str(random.nextInt());
result = request1.POST("http://localhost:8080/transactions/add",
"{"'"customerRewardsId"'":null,"'"customerId"'":"+ customerId + ","'"transactionDate"'":null}")
txnId = parseJsonString(result.getText(), "id")
3.5. The Grinder
Без функционального программирования Scala и графического интерфейса наш Jython-скрипт для The Grinder выглядит довольно просто. Добавьте несколько системных классов Java, и у нас будет намного меньше строк кода.
grinder.threads = 100
grinder.processes = 1
grinder.runs = 1000
Однако меньшее количество строк кода настройки теста уравновешивается потребностью в большем количестве кода обслуживания строк, такого как синтаксический анализ строк JSON. Кроме того, API HTTPRequest ограничен по функциональности.
В The Grinder мы определяем значения потоков, процессов и запусков во внешнем файле свойств:
Наш полный Jython-скрипт для The Grinder будет выглядеть следующим образом.
4. Тестовые запуски
4.1. Выполнение теста
Все три инструмента рекомендуют использовать командную строку для тестов с большой нагрузкой.
./gatling.sh
Для запуска тестов мы будем использовать Gatling версии 3.4.0 с открытым исходным кодом в качестве отдельного инструмента, JMeter 5.3 и The Grinder версии 3.
Gatling требует только наличия JAVA_HOME и GATLING_HOME. Для запуска Gatling мы используем:
./jmeter.sh -n -t TestPlan.jmx -l log.jtl
в каталоге GATLING_HOME/bin.
export CLASSPATH=/home/lore/Documents/grinder-3/lib/grinder.jar:$CLASSPATH
export GRINDERPROPERTIES=/home/lore/Documents/grinder-3/examples/grinder.properties
JMeter нужен параметр, чтобы отключить графический интерфейс для теста, как было предложено при запуске графического интерфейса для настройки:
Как и Gatling, Grinder требует, чтобы мы установили JAVA_HOME и GRINDERPATH. Однако ему также нужны еще несколько свойств:
java -classpath $CLASSPATH net.grinder.Console
java -classpath $CLASSPATH net.grinder.Grinder $GRINDERPROPERTIES
Как упоминалось выше, мы предоставляем файлgrinder.properties для дополнительной настройки, такой как потоки, запуски, процессы и хосты консоли.
Наконец, мы загружаем консоль и агентов с помощью:
Successful Requests | Errors | Total Test Time (s) | Average Response Time (ms) | Mean Throughput | |
Gatling | 500000 Requests | 0 | 218s | 42 | 2283 req/s |
JMeter | 499997 Requests | 0 | 237s | 46 | 2101 req/s |
The Grinder | 499997 Requests | 0 | 221s | 43 | 2280 req/s |
4.2. Результаты тестов
В каждом тесте было выполнено 1000 прогонов со 100 пользователями/потоками. Давайте раскроем некоторые основные моменты:
Результаты показывают, что 3 инструмента имеют одинаковую скорость, а Гатлинг немного опережает другие 2, исходя из средней пропускной способности.
Каждый инструмент также предоставляет дополнительную информацию в более удобном пользовательском интерфейсе.
Gatling сгенерирует отчет в формате HTML в конце выполнения, который содержит несколько графиков и статистических данных как для всего выполнения, так и для каждого запроса. Вот фрагмент отчета о результатах теста:
При использовании JMeter мы можем открыть графический интерфейс после запуска теста и создать отчет HTML на основе файла журнала, в котором мы сохранили результаты:
Отчет JMeter HTML также содержит разбивка статистики по запросу.
Наконец, консоль Grinder записывает статистику для каждого агента и запуска:
Gatling | JMeter | The Grinder | |
Project and Community | 9 | 9 | 6 |
Performance | 9 | 8 | 9 |
Scriptability/API | 7 | 9 | 8 |
UI | 9 | 8 | 6 |
Reports | 9 | 7 | 6 |
Integration | 7 | 9 | 7 |
Summary | 8.3 | 8.3 | 7 |
Несмотря на то, что Grinder является высокоскоростным, это достигается за счет дополнительного времени разработки и меньшего разнообразия выходных данных.
-
5. Резюме
Теперь пришло время бросить общий взгляд на каждый из инструментов нагрузочного тестирования.
-
Gatling:
Надежный, отполированный инструмент для нагрузочного тестирования, который выводит красивые отчеты со сценариями Scala. Уровни поддержки Open Source и Enterprise для продукта
-
JMeter:
Надежный API (через графический интерфейс) для разработки тестовых сценариев без требуется кодирование. Поддержка Apache Foundation и отличная интеграция с Maven.
The Grinder:
Инструмент быстрого нагрузочного тестирования для разработчиков, использующих Jython. необходимость, затем используйте The Grinder.
Если великолепно выглядящие интерактивные графики помогают показать прирост производительности в пользу изменений, используйте Gatling.
JMeter — это инструмент для сложной бизнес-логики или уровня интеграции со многими типами сообщений. Являясь частью Apache Software Foundation, JMeter предоставляет зрелый продукт и большое сообщество.
6. Заключение