- PVSM.RU - https://www.pvsm.ru -
Статья публикуется от имени Перфильева Алексея, akaaxel [1]
Gatling [2]– это framework для проведения нагрузочного тестирования. Он основан на трех технологиях: Scala, Akka и Netty.
В этой статье мы:
Большинство специалистов для нагрузки используют Jmeter — до тех пор, пока не понадобится нагружать сокеты.
Мы нашли плагин для Jmeter. [3] Плагин показал плохую производительность: программа работала нестабильно уже при ста открытых коннектах. Gatling стал хорошей заменой: он содержит программный интерфейс нагрузки сокетов и выдерживает до 5000 открытых соединений без сбоев.
Когда мы познакомились с Gatling — его синтаксисом и возможностями — стали переводить все скрипты с Jmeter на Gatling.
Устанавливаем Scala SDK и SBT [4], чтобы создавать скрипты и запускать их в IDE — например, в IntelliJ IDEA с поддержкой SBT проектов.
Структура проекта:
Скрипт размещаем в /src/test/scala/. Чтобы запустить симуляцию из-под sbt, добавляем в plugins.sbt строчку:
addSbtPlugin("io.gatling" % "gatling-sbt" % "2.2.0")
В build.sbt добавляем:
enablePlugins(GatlingPlugin)
libraryDependencies += "io.gatling.highcharts" % "gatling-charts-highcharts" % "2.2.2" % "test"
libraryDependencies += "io.gatling" % "gatling-test-framework" % "2.2.2" % "test"
Idea выдаст ошибку на строку enablePlugins(GatlingPlugin) [5], но эта проблема IDE.
Теперь мы готовы разработать скрипт нагрузки.
Любой скрипт на Gatling состоит из двух частей: конфигурации и самого профиля.
Задаем файл с данными о пользователях, которые нагрузят систему:
val users = ssv(fileName).circular
ssv (semicolon separated values ) — формат файла. Ему не обязательно совпадать с расширением файла. В документации [6] можно посмотреть другие поддерживаемые форматы файлов.
fileName — строка с абсолютным именем файла ( C:datausers.csv )
circular — метод обхода значений в файле. У нас: когда доходим до последней строки с пользователем, возвращаемся в начало.
Дальше задаем конфиг http — он будет работать для всех запросов:
val httpConf = http
.baseURL("https://www.tinkoff.ru/ ")
.acceptHeader("*/*")
.acceptEncodingHeader("gzip, deflate, br")
.acceptLanguageHeader("ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3")
.userAgentHeader("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0")
.check(status is 200)
Здесь задаем нужные хедеры, базовый URL и другие настройки: например, указываем прокси или отключаем кеширование.
Создаем сценарий:
val basicLoad = scenario("BASIC_LOAD").feed(users).during(20 minutes) {
exec(BasicLoad.start)
}
setUp(
basicLoad.inject(rampUsers(1000) over (20 minutes))
.protocols(httpConf))
.maxDuration(21 minutes)
Конфигурация должна содержаться в классе, расширяющий класс Simulation
package load
import io.gatling.core.scenario.Simulation
class LoadScript extends Simulation{
// Здесь наш конфиг
}
Посмотрите на полный проект. [7] Мы создаем сценарий, где используем наших пользователей и конфиг http. За 20 минут скрипт прогонит профиль BasicLoad.start. Если сервер повиснет, на 21-й минуте прогон принудительно завершится. Мы получим отчет по всем данным, которые успели попасть в лог.
object BasicLoad {
val start =
exec(
http("HTTP Request auth")
.post("/rest/session-start")
.formParam("login", "${login}")
.formParam("password", "${password}")
)
.exec(
http("HTTP Request getSkills")
.get("/rest/skills")
.check(jsonPath("$.id").saveAs("idSkill"))
)
.exec(
http("HTTP Request getResults")
.get("/rest/results")
.check(jsonPath("$.id").saveAs("idResult"))
)
.repeat(15) {
exec(session => {
println("Some Log")
val tmp = getTen()
session.set("ten",tmp)
})
.exec(
http("HTTP Request completedtasksreport skill")
.get("/rest/v2/completedtasksreport/")
.queryParam("dateFrom", "${data}")
.queryParam("excludeNoAnswer", "false")
.queryParam("orderBy", "ResultDate")
.queryParam("orderDesc", "true")
.queryParam("skip", "0")
.queryParam("take",_.attributes.getOrElse("ten",None))
.queryParam("skillIds", "${idSkill}")
)
.exec(
http("HTTP Request completedtasksreport result")
.get("/rest/v2/completedtasksreport/")
.queryParam("dateFrom", "${data}")
.queryParam("excludeNoAnswer", "false")
.queryParam("orderBy", "ResultDate")
.queryParam("orderDesc", "true")
.queryParam("skip", "0")
.queryParam("take", _.attributes.getOrElse("idSkill",None))
.queryParam("resultId", "${idResult}")
)
.exec(
http("HTTP Request completedtasksreport skill and result")
.get("/rest/v2/completedtasksreport/")
.queryParam("dateFrom", "${data}")
.queryParam("excludeNoAnswer", "false")
.queryParam("orderBy", "ResultDate")
.queryParam("orderDesc", "true")
.queryParam("skip", "0")
.queryParam("take", _.attributes.getOrElse("idSkill",None))
.queryParam("skillIds", "${idSkill}")
.queryParam("resultId", "${idResult}")
)
}
}
exec — метод, по которому нагрузочный профиль выполняет единичное действие. Например, отправляет запрос, открывает сокет, отправляет сообщение по сокету или выполняет анонимную функцию.
http(samplerName: String).(get|post|put…) отправляет необходимый запрос http. В функции метода http указываем относительный путь. Базовый url мы уже указали при настройке конфига http. Далее указываем параметры запроса — queryParam | formParam.
check проверяет ответ. Можно проверить заголовок ответа. Мы также используем check, когда хотим проверить и сохранить тело ответа или его отдельные элементы.
Любые действия можно выполнить с помощью конструкции:
exec( session => {
// ваш код
})
Внутри этого блока мы ограничиваемся только возможностями Scala. Сессия, с которой мы работаем, уникальна для каждого юзера (потока). Поэтому можно задать для сессии параметры через set, чтобы они были доступны в других блоках exec. Получить доступ к заданным параметрам можно через вызов
"${idSkill}"
или
_.attributes.getOrElse("idSkill",None)
Запускаем Gatling с помощью sbt.
> sbt
> gatling:testOnly load.LoadScript
Во время запуска в консоль будут поступать данные в формате:
2017-02-02 10:49:27 20s elapsed
---- BASIC_LOAD --------------------------------------------------------------------
[--------------------------------------------------------------------------] 0%
waiting: 0 / active: 10 / done:0
---- Requests ------------------------------------------------------------------
> Global (OK=5155 KO=0 )
> HTTP Request auth (OK=111 KO=0 )
> HTTP Request getSkills (OK=111 KO=0 )
> HTTP Request getResults (OK=111 KO=0 )
> HTTP Request completedtasksreport skill (OK=1610 KO=0 )
> HTTP Request completedtasksreport result (OK=1607 KO=0 )
> HTTP Request completedtasksreport skill and result (OK=1605 KO=0 )
Если какие-нибудь методы упадут, мы сразу увидим ошибку:
status.find.is(200), but actually found 500 1 (100,0%)
и запись в KO.
После прогона отчет попадет в папку /target/gatling/SCRIPT_NAME-TIMESTAMP.
В отчете мы видим все необходимые графики, включая персентили, количество запросов в секунду и распределение времени ответа. Также отчет содержит таблицу с полной информацией по методам:
Если нас интересует конкретный метод, отдельно смотрим статистику по нему:
Если запуск скрипта и анализ результатов проводит ваш коллега, подготовьте его машину:
После этого начнется нагрузка. Результаты попадут в папку /results. Чтобы посмотреть их, откройте index.html в любом браузере.
В архиве вы найдете утилиту recorder. С ее помощью можно сгенерировать скрипт двумя способами:
Генерация скрипта с использованием рекордера не идеальна — в скрипте много «воды» и нет функций проверки ответов. Отчет трудно читать, методы в нем называются request_0, request_1 и т. д.
В статье мы поговорили только об основных функциях Gatling. Это гибкий фреймворк, его возможности намного шире.
В следующей статье:
Напишите в комментариях, что вы хотели бы обсудить подробнее.
Автор: Tinkoff.ru
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/framework/248282
Ссылки в тексте:
[1] akaaxel: https://habrahabr.ru/users/akaaxel/
[2] Gatling : http://gatling.io/#/
[3] плагин для Jmeter.: https://github.com/maciejzaleski/JMeter-WebSocketSampler
[4] Scala SDK и SBT: https://habrahabr.ru/post/231971/
[5] ошибку на строку enablePlugins(GatlingPlugin): https://github.com/JetBrains/intellij-sbt/blob/master/idea-plugin/src/main/scala/org/jetbrains/sbt/language/SbtAnnotator.scala#L41
[6] В документации: http://gatling.io/#/cheat-sheet/2.2.3
[7] полный проект.: https://github.com/akaAXeL/exampleLoad
[8] архив: https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/2.2.3/gatling-charts-highcharts-bundle-2.2.3-bundle.zip
[9] Источник: https://habrahabr.ru/post/323316/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.