The article is published on behalf of Alexey Perfilyev, akaaxel
Gatling is a framework for 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 us examine the syntax of scripts Gatling language Scala.
- Let's write a small test where we use the main functions of Gatling. Run the test script with sbt and save the report.
Why gatling
Most professionals use Jmeter for workload until they need to load sockets.
We found a
plugin for Jmeter. The plugin showed poor performance: the program was unstable already with a hundred open connections. Gatling has become a good replacement: it contains a software interface for loading sockets and can withstand up to 5,000 open connections without fail.
')
When we met Gatling - its syntax and capabilities - we began to translate all the scripts from Jmeter to Gatling.
Preparing to work with Gatling
Install
Scala SDK and SBT to create scripts and run them in IDE - for example, in IntelliJ IDEA with support for SBT projects.
Project structure:

The script is placed in
/ src / test / scala / . To run the simulation from under sbt, add the following line to plugins.sbt:
addSbtPlugin("io.gatling" % "gatling-sbt" % "2.2.0")
Add to 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 will give an
error on the line enablePlugins (GatlingPlugin) , but this is an IDE problem.
Now we are ready to develop a load script.
Syntax
Any Gatling script consists of two parts: the configuration and the profile itself.
Configuration:
We set a file with data about users that will 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 is a string with an absolute file name (C: \ data \ users.csv)
circular - a method of traversing values ​​in a file. With us: when we reach 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 script where we use our users and the http config. For 20 minutes, the script will run the BasicLoad.start profile. If the server hangs, in the 21st minute the run will be forced to end. We will receive a report on all 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 - the method by which the load profile performs a single action. For example, it sends a request, opens a socket, sends a message on 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, we indicate the relative path. We have already specified the base url when configuring the http config. Next, we specify the query parameters -
queryParam | formParam .
check checks the answer. 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 following construction:
exec( session => {
Inside this block we are limited only by the capabilities of Scala. The session we work with is unique for 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
Run Gatling using sbt.
> sbt
> gatling:testOnly load.LoadScript
During launch, the console will receive data in the following format:
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 )
If any methods fall, we will immediately see the error:
status.find.is(200), but actually found 500 1 (100,0%)
and an entry in 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 complete information on the methods:

If we are interested in a specific method, separately we look at the statistics on it:

Load testing from another machine
If running a script and analyzing the results is carried out by your colleague, prepare his car:
- Download the archive . Unpack and copy your script into the folder / user-files / simulations / .
- Open the / bin folder and run gatling. <Bat | sh> .
- Select your script in the command line, click 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. With its help, you can generate a script in two ways:
- based on the HAR archive - dump network tabs in the developer window in the browser
- using the utility as a proxy between the browser and the web server
Generating a script using a recorder is not perfect - there is a lot of “water” in the script and there are no functions for checking answers. The report is difficult to read, the methods in it are called
request_0, request_1, and so on.
What's next
In the article we talked only about the main functions of Gatling. This is a flexible framework, its capabilities are much broader.
In the following article:
- Consider the load of sockets.
- We analyze random branching.
- Let's set RPS.
- Compare the performance of Gatling with Jmeter.
Write in the comments that you would like to discuss in more detail.