Gatling Load Testing
- Tutorial
The article is published on behalf of Alexey Perfiliev, akaaxel
Gatling is a framework for conducting load testing. It is based on three technologies: Scala, Akka and Netty.
In this article we:
Most experts use Jmeter for load until they need to load sockets.
We found a plugin for Jmeter. The plugin showed poor performance: the program worked unstable even with a hundred open connections. Gatling is a good replacement: it contains a socket load programming interface and can withstand up to 5000 open connections without fail.
When we met Gatling - its syntax and capabilities - we began to translate all scripts from Jmeter to Gatling.
Install the Scala SDK and SBT to create scripts and run them in the IDE - for example, in IntelliJ IDEA with support for SBT projects.
Project structure: We place the
script in / src / test / scala / . To start the simulation from under sbt, add the line to plugins.sbt:
In build.sbt add:
Idea will throw an error on the enablePlugins (GatlingPlugin) line , but this is an IDE problem.
Now we are ready to develop a load script.
Any Gatling script consists of two parts: configuration and the profile itself.
We set the file with data about users who load the system:
ssv (semicolon separated values) - file format. It does not have to match the file extension. See the documentation for other supported file formats.
fileName - a string with an absolute file name (C: \ data \ users.csv)
circular - a method of traversing values in a file. With us: when we get to the last line with the user, we return to the beginning.
Next, we set the http config - it will work for all requests:
Here we set the necessary headers, base URL and other settings: for example, specify a proxy or disable caching.
Create a script:
The configuration must be contained in a class that extends the Simulation class.
Look at the complete project. We create a scenario where we use our users and the http config. In 20 minutes, the script will run the BasicLoad.start profile. If the server hangs, in the 21st minute, the run is forcibly terminated. We will receive a report on all the data that managed to get into the log.
exec is the method by which the load profile performs a single action. For example, it sends a request, opens a socket, sends a message over a socket, or performs an anonymous function.
http (samplerName: String). (get | post | put ...) sends the required http request. In the function of the http method, specify the relative path. We already specified the base url when configuring the http config. Next, specify the query parameters - queryParam | formParam .
check checks the response. You can check the response header. We also use check when we want to check and save the response body or its individual elements.
Any actions can be performed using the design:
Inside this block, we are limited only by the capabilities of Scala. The session with which we work is unique to each user (stream). Therefore, you can set parameters for the session through set so that they are available in other exec blocks. You can access the specified parameters through a call
or
Launch Gatling with sbt. During startup, the console will receive data in the format: If any methods fall, we will immediately see an error: and write to KO. After the run, the report will go to the / target / gatling / SCRIPT_NAME-TIMESTAMP folder . In the report we see all the necessary graphs, including percentiles, the number of requests per second and the distribution of response time. The report also contains a table with full information on the methods: If we are interested in a particular method, we separately look at the statistics on it:
If your colleague runs the script and analyzes the results, prepare his machine:
After that, the load will begin. The results will go to the / results folder . To view them, open index.html in any browser.
In the archive you will find the recorder utility . Using it, you can generate a script in two ways:
Generating a script using a recorder is not ideal - there is a lot of “water” in the script and there are no functions for checking responses. The report is difficult to read, the methods in it are called request_0, request_1 , etc.
In the article, we talked only about the basic functions of Gatling. This is a flexible framework, its capabilities are much wider.
In the following article:
Write in the comments what you would like to discuss in more detail.
Gatling is a framework for conducting load testing. It is based on three technologies: Scala, Akka and Netty.
In this article we:
- Let's see how to install and start using Gatling.
- Let's analyze the syntax of Gatling scripts in Scala.
- We will write a short test where we use the basic functions of Gatling. Run the test script using sbt and save the report.
Why gatling
Most experts use Jmeter for load until they need to load sockets.
We found a plugin for Jmeter. The plugin showed poor performance: the program worked unstable even with a hundred open connections. Gatling is a good replacement: it contains a socket load programming interface and can withstand up to 5000 open connections without fail.
When we met Gatling - its syntax and capabilities - we began to translate all scripts from Jmeter to Gatling.
Preparing to work with Gatling
Install the Scala SDK and SBT to create scripts and run them in the IDE - for example, in IntelliJ IDEA with support for SBT projects.
Project structure: We place the
script in / src / test / scala / . To start the simulation from under sbt, add the line to plugins.sbt:
addSbtPlugin("io.gatling" % "gatling-sbt" % "2.2.0")
In build.sbt add:
enablePlugins(GatlingPlugin)
libraryDependencies += "io.gatling.highcharts" % "gatling-charts-highcharts" % "2.2.2" % "test"
libraryDependencies += "io.gatling" % "gatling-test-framework" % "2.2.2" % "test"
Idea will throw an error on the enablePlugins (GatlingPlugin) line , but this is an IDE problem.
Now we are ready to develop a load script.
Syntax
Any Gatling script consists of two parts: configuration and the profile itself.
Configuration:
We set the file with data about users who load the system:
val users = ssv(fileName).circular
ssv (semicolon separated values) - file format. It does not have to match the file extension. See the documentation for other supported file formats.
fileName - a string with an absolute file name (C: \ data \ users.csv)
circular - a method of traversing values in a file. With us: when we get to the last line with the user, we return to the beginning.
Next, we set the http config - it will work for all requests:
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)
Here we set the necessary headers, base URL and other settings: for example, specify a proxy or disable caching.
Create a script:
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)
The configuration must be contained in a class that extends the Simulation class.
package load
import io.gatling.core.scenario.Simulation
class LoadScript extends Simulation{
// Здесь наш конфиг
}
Look at the complete project. We create a scenario where we use our users and the http config. In 20 minutes, the script will run the BasicLoad.start profile. If the server hangs, in the 21st minute, the run is forcibly terminated. We will receive a report on all the data that managed to get into the log.
Load profile:
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 is the method by which the load profile performs a single action. For example, it sends a request, opens a socket, sends a message over a socket, or performs an anonymous function.
http (samplerName: String). (get | post | put ...) sends the required http request. In the function of the http method, specify the relative path. We already specified the base url when configuring the http config. Next, specify the query parameters - queryParam | formParam .
check checks the response. You can check the response header. We also use check when we want to check and save the response body or its individual elements.
Any actions can be performed using the design:
exec( session => {
// ваш код
})
Inside this block, we are limited only by the capabilities of Scala. The session with which we work is unique to each user (stream). Therefore, you can set parameters for the session through set so that they are available in other exec blocks. You can access the specified parameters through a call
"${idSkill}"
or
_.attributes.getOrElse("idSkill",None)
Launch and Report
Launch Gatling with sbt. During startup, the console will receive data in the format: If any methods fall, we will immediately see an error: and write to KO. After the run, the report will go to the / target / gatling / SCRIPT_NAME-TIMESTAMP folder . In the report we see all the necessary graphs, including percentiles, the number of requests per second and the distribution of response time. The report also contains a table with full information on the methods: If we are interested in a particular method, we separately look at the statistics on it:
> 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%)
Load testing from another machine
If your colleague runs the script and analyzes the results, prepare his machine:
- Download the archive . Unzip and copy your script to the / user-files / simulations / folder .
- Open the / bin folder and run gatling.
. - Select your script on the command line, press the desired number.
After that, the load will begin. The results will go to the / results folder . To view them, open index.html in any browser.
In the archive you will find the recorder utility . Using it, you can generate a script in two ways:
- based on the HAR archive - network dump-tabs in the browser window of the developer
- using the utility as a proxy between the browser and the web server
Generating a script using a recorder is not ideal - there is a lot of “water” in the script and there are no functions for checking responses. The report is difficult to read, the methods in it are called request_0, request_1 , etc.
What's next
In the article, we talked only about the basic functions of Gatling. This is a flexible framework, its capabilities are much wider.
In the following article:
- Consider the load of sockets.
- Let's analyze random branching.
- Set RPS.
- Compare Gatling performance with Jmeter.
Write in the comments what you would like to discuss in more detail.