1. Введение
Выбор правильного инструмента для работы может быть пугающим. В этом руководстве мы упростим это, сравнив три инструмента нагрузочного тестирования веб-приложений - Apache JMeter, Gatling и The Grinder - с простым REST API.
2. Инструменты тестирования нагрузки
Во-первых, давайте быстро рассмотрим некоторые из них.
2.1. Гатлинга
Gatling - инструмент для нагрузочного тестирования, который создает тестовые сценарии в Scala. Регистратор Гатлинга генерирует тестовые сценарии Scala, ключевую функцию для Гатлинга. Для получения дополнительной информации ознакомьтесь с нашим учебником Intro to Gatling .
2.2. JMeter
JMeter - это инструмент нагрузочного тестирования Apache. Он предоставляет приятный графический интерфейс, который мы можем использовать для конфигурации. Уникальная функция, называемая логическими контроллерами, дает большую гибкость при настройке тестов в графическом интерфейсе. **
Посетите наш учебник Intro to JMeter для получения снимков экрана и получения дополнительных пояснений.
2.3. Дробилка
И наш последний инструмент, The Grinder , предоставляет более мощный движок сценариев, чем два других, и использует Jython. Тем не менее, Grinder 3 имеет функциональность для записи сценариев.
Grinder также отличается от двух других инструментов тем, что допускает процессы консоли и агента. Эта функциональность обеспечивает возможность процесса агента, чтобы нагрузочные тесты могли масштабироваться на нескольких серверах. Он специально рекламируется как инструмент нагрузочного тестирования, созданный для разработчиков, чтобы находить тупики и замедления.
3. Настройка тестового набора
Далее для нашего теста нам нужен API. Наша функциональность API включает в себя:
-
добавить/обновить запись вознаграждений
-
просмотреть одну/все награды
-
привязать транзакцию к записи о вознаграждениях клиентов
-
просмотр транзакций для записи вознаграждений клиентов
-
Наш сценарий: **
У магазина есть общенациональная распродажа с новыми и постоянными покупателями, которым нужны учетные записи клиентов для получения сбережений. API вознаграждений проверяет учетную запись вознаграждения клиента по идентификатору клиента _. _ Если учетная запись вознаграждения не существует, добавьте ее, затем укажите ссылку на транзакцию.
После этого мы запрашиваем транзакции.
3.1. Наш ОТДЫХ 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)
Обратите внимание на некоторые отношения, такие как запрос транзакций по идентификатору вознаграждения и получение учетной записи вознаграждения по идентификатору клиента __. __Эти отношения вынуждают некоторую логику и некоторый анализ ответов для создания нашего тестового сценария.
-
К счастью, все наши инструменты справляются с этим довольно хорошо, некоторые лучше, чем другие. **
3.2. Наш план тестирования
Далее нам нужны тестовые скрипты.
Чтобы получить достоверное сравнение, мы выполним те же шаги автоматизации для каждого инструмента:
, Генерация случайных идентификаторов учетных записей клиентов
, Опубликовать транзакцию
, Разобрать ответ на случайный идентификатор клиента и идентификатор транзакции
, Запрос идентификатора учетной записи вознаграждения клиента с идентификатором клиента
, Разберите ответ по идентификатору учетной записи вознаграждений
, Если идентификатора учетной записи вознаграждений не существует, добавьте его с сообщением
, Проводите ту же первоначальную транзакцию с обновленным идентификатором вознаграждений, используя
номер транзакции , Запросить все транзакции по идентификатору учетной записи вознаграждений
Давайте подробнее рассмотрим шаг 4 для каждого инструмента. И не забудьте проверить The sample для всех трех завершенных сценариев .
3.3. Гатлинга
Для Гатлинга знакомство со Scala добавляет благ для разработчиков, поскольку API Гатлинга является надежным и содержит множество функций.
API Гатлинга использует подход DSL-компоновщика, как мы видим на шаге 4:
.exec(http("get__reward")
.get("/rewards/find/${custId}")
.check(jsonPath("$.id").saveAs("rwdId")))
.pause(1)
Особо следует отметить поддержку Gathling JSON Path, когда нам нужно прочитать и проверить ответ HTTP. Здесь мы подберем идентификатор награды и сохраним его во внутреннем состоянии Гатлинга. Обратите внимание на паузу в одну секунду, эта необходимая проверка предотвращает сбой следующего зависимого запроса. Вызов check и saveAs не блокировали последующие запросы exec .
Кроме того, язык выражений Гатлинга упрощает динамическое тело запроса Strings:
.body(StringBody(
"""{
"customerRewardsId":"${rwdId}",
"customerId":"${custId}",
"transactionDate":"${txtDate}"
}""")).asJson)
Наконец наша конфигурация для этого сравнения. 10 прогонов, заданных как повторение всего сценария, __atOnceUsers __method устанавливает потоки/пользователей:
val scn = scenario("RewardsScenario")
.repeat(10) {
...
}
setUp(
scn.inject(atOnceUsers(100))
).protocols(httpProtocol)
-
Https://github.com/eugenp/tutorials/tree/master/testing-modules/load-testing-comparison/src/main/resources/scripts[entire 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 и LoopController :
<stringProp name="LoopController.loops">10</stringProp>
<stringProp name="ThreadGroup.num__threads">100</stringProp>
View весь файл jmx в качестве ссылки . Хотя это возможно, написание тестов в XML в виде файлов .jmx не имеет смысла с полнофункциональным графическим интерфейсом.
3.5. Дробилка
Без функционального программирования Scala и GUI наш 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. Кроме того, HTTPRequest API имеет небольшую функциональность.
С помощью Grinder мы определяем потоки, обрабатываем и запускаем значения во внешнем файле свойств:
grinder.threads = 100
grinder.processes = 1
grinder.runs = 10
-
Наш полный сценарий Jython для The Grinder будет выглядеть следующим образом: this .**
4. Тестовые прогоны
4.1. Выполнение теста
Все три инструмента рекомендуют использовать командную строку для тестов с большой нагрузкой.
Гатлинг требует только того, чтобы у нас были установлены JAVA HOME и GATLING HOME .
Для выполнения Гатлинга мы используем:
GATLING__HOME\bin\gatling.bat
JMeter нужен параметр, чтобы отключить графический интерфейс для теста, как было предложено при запуске графического интерфейса для конфигурации:
jmeter-n.cmd -t -l TestPlan.jmx -e -o[path to output folder]----
Как и Гатлинг, Grinder требует, чтобы мы установили __JAVA__HOME__ и __GRINDERPATH__. Тем не менее, ему нужно еще несколько свойств:
[source,powershell,gutter:,true]
set GRINDERPROPERTIES="%GRINDERPATH%\grinder.properties" set CLASSPATH="%GRINDERPATH%\lib\grinder.jar";%CLASSPATH%
Как упоминалось выше, мы предоставляем файл __grinder.properties__ для дополнительной настройки, такой как потоки, запуски, процессы и хосты консоли. Наконец, мы загружаем консоль и агентов с помощью: [source,powershell,gutter:,true]
java -classpath %CLASSPATH% net.grinder.Console
[source,powershell,gutter:,true]
java -classpath %CLASSPATH% net.grinder.Grinder %GRINDERPROPERTIES%
==== 4.2. Результаты теста Каждый из тестов проводился по десять прогонов с 100 пользователями/потоками. Давайте распакуем некоторые из основных моментов: [cols=",^,^,^,^,^",] | ================================================= ====================== | | ** Успешные запросы ** | ** Ошибки ** | ** Общее время тестирования (с) ** | ** Среднее время ответа (мс) ** | ** Пиковая пропускная способность ** | ** Gatling ** | 4100 запросов | 100 (soft) ** | 31 | 64,5 | 132 req/s | ** JMeter ** | 4135 Запросов | 0 | 35 | 81 | 1080 req/s | ** Grinder ** | 5000 запросов | 0 | 5.57 | 65.72 | 1284 req/s | =================================== ========================================= Взгляд показывает, что Grinder работает в 6 раз быстрее, чем два других инструмента для полного тестирования. Два других такта работали примерно через 30 секунд. Один и тот же шаг между The Grinder и Gatling, создав 100 потоков, занял 1544 мс и 16 мс соответственно. И хотя Grinder высокоскоростен, он идет за счет дополнительного времени разработки и меньшего разнообразия выходных данных. Дополнительное примечание У Гатлинга 100 «мягких» сбоев из-за логической проверки несуществующего идентификатора вознаграждения. Другие инструменты не считают условный сбой ошибкой. Это ограничение запечатлено в Gatling API. [[test-summary]] === 5. Резюме Теперь пришло время взглянуть на каждый из инструментов нагрузочного тестирования. [cols="^,^,^,^",] | ==================================== | | ** Gatling ** | ** JMeter ** | ** The Grinder ** | Проект и сообщество | 9 | 9 | 6 | Производительность | 7 | 7 | 10 | Скриптистит/API | 7 | 9 | 8 | UI | 8 | 8 | 5 | Отчеты | 9 | 7 | 6 | Интеграция | 7 | 9 | 7 | ** Сводка ** | ** 7,8 ** | ** 8,2 ** | ** 7 ** | ======================= ================== ** Гатлинга: ** ** Твердый, отточенный инструмент для нагрузочного тестирования, который выводит красивые отчеты с Scala скриптинг ** Уровни поддержки Open Source и Enterprise для продукта ** JMeter: ** ** Надежный API (через GUI) для разработки тестовых скриптов без программирования требуется ** Поддержка Apache Foundation и отличная интеграция с Maven ** Мясорубка: ** ** Быстрый инструмент для нагрузочного тестирования производительности для разработчиков, использующих Jython ** Межсерверная масштабируемость обеспечивает еще больший потенциал для больших тестов Проще говоря, если скорость и масштабируемость необходимы, используйте Grinder. Если хорошо выглядящие интерактивные графики помогают показать выигрыш в производительности, чтобы аргументировать изменения, используйте Gatling. JMeter - это инструмент для сложной бизнес-логики или уровня интеграции со многими типами сообщений. Как часть Apache Software Foundation, JMeter предоставляет зрелый продукт и большое сообщество. === 6. Заключение В заключение мы видим, что инструменты имеют сравнимые функциональные возможности в одной области, в то время как в других они сияют. Правильный инструмент для правильной работы - разговорная мудрость, которая работает в разработке программного обеспечения. Наконец, API и скрипты можно найти https://github.com/eugenp/tutorials/tree/master/testing-modules/load-testing-comparison[on Github].