Gatlingを使って負荷テストを実施する

Gatlingを使って負荷テストを実施します。

Gatlingとは

Gatlingとはハイパフォーマンスな負荷テストツールです。
テストシナリオはScalaで書きます。

公式サイト:https://gatling.io/

Gatlingを実行する方法はいくつかあるみたいですが、ここではsbtタスクで実行します。

sbtをインストールします。

実行にはsbtが必要です。以下のサイトからsbtをダウンロードしてパスを通してください。
https://www.scala-sbt.org/download.html

sbtとはMavenのようなビルドツールです。
scalaでよく使われていますが、javaでも使えるみたいです。

sbtタスクで実行する

sbtタスクで実行する際のドキュメント:https://gatling.io/docs/current/extensions/sbt_plugin/#sbt-plugin

実行にはsbtプラグインを使うのですが、以下のデモプロジェクトを動かしてみるのが手っ取り早いです。

https://github.com/gatling/gatling-sbt-plugin-demo

プロジェクトの例

sbt=1.3.2、scala=2.12.9でプロジェクトを1から作ってみました。
scalaのバージョンが2.13.xだと動かないので注意してください。2.12.xを使いましょう。
参考:https://github.com/gatling/gatling/issues/3566

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.
│ build.sbt

├─project
│ build.properties
│ plugins.sbt

└─src
└─test
├─resources
│ gatling.conf

└─scala
└─kujilabo
Shelfy.scala

build.sbt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name := "gatling-001"

version := "0.1"

enablePlugins(GatlingPlugin)

//scalaVersion := "2.13.1"

scalaVersion := "2.12.9"

scalacOptions := Seq(
"-encoding", "UTF-8", "-target:jvm-1.8", "-deprecation",
"-feature", "-unchecked", "-language:implicitConversions", "-language:postfixOps")

libraryDependencies += "io.gatling.highcharts" % "gatling-charts-highcharts" % "3.2.1" % "test"
libraryDependencies += "io.gatling" % "gatling-test-framework" % "3.2.1" % "test"

build.properties

1
sbt.version = 1.3.2

plugins.sbt

1
addSbtPlugin("io.gatling" % "gatling-sbt" % "3.0.0")

gatling.conf

デモプロジェクトのコピーです。
https://github.com/gatling/gatling-sbt-plugin-demo/blob/master/src/test/resources/gatling.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#########################
# Gatling Configuration #
#########################

# This file contains all the settings configurable for Gatling with their default values

gatling {
core {
#outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp)
#runDescription = "" # The description for this simulation run, displayed in each report
#encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation
#simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated)
#elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable
#rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable
#rawFileBodiesInMemoryMaxSize = 1000 # Below this limit, raw file bodies will be cached in memory
#pebbleFileBodiesCacheMaxCapacity = 200 # Cache size for request body Peeble templates, set to 0 to disable
#shutdownTimeout = 5000 # Milliseconds to wait for the actor system to shutdown
extract {
regex {
#cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching
}
xpath {
#cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching
}
jsonPath {
#cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching
#preferJackson = false # When set to true, prefer Jackson over Boon for JSON-related operations
}
css {
#cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching
}
}
directory {
#simulations = user-files/simulations # Directory where simulation classes are located (for bundle packaging only)
#resources = user-files/resources # Directory where resources, such as feeder files and request bodies are located (for bundle packaging only)
#reportsOnly = "" # If set, name of report folder to look for in order to generate its report
#binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target.
#results = results # Name of the folder where all reports folder are located
}
}
charting {
#noReports = false # When set to true, don't generate HTML reports
#maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports
#useGroupDurationMetric = false # Switch group timings from cumulated response time to group duration.
indicators {
#lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary
#higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary
#percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and Graphite
#percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and Graphite
#percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and Graphite
#percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and Graphite
}
}
http {
#fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable
#fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable
#perUserCacheMaxCapacity = 200 # Per virtual user cache size, set to 0 to disable
#warmUpUrl = "https://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled)
#enableGA = true # Very light Google Analytics, please support
ssl {
keyStore {
#type = "" # Type of SSLContext's KeyManagers store
#file = "" # Location of SSLContext's KeyManagers store
#password = "" # Password for SSLContext's KeyManagers store
#algorithm = "" # Algorithm used SSLContext's KeyManagers store
}
trustStore {
#type = "" # Type of SSLContext's TrustManagers store
#file = "" # Location of SSLContext's TrustManagers store
#password = "" # Password for SSLContext's TrustManagers store
#algorithm = "" # Algorithm used by SSLContext's TrustManagers store
}
}
ahc {
#connectTimeout = 10000 # Timeout in millis for establishing a TCP socket
#handshakeTimeout = 10000 # Timeout in millis for performing TLS handshake
#pooledConnectionIdleTimeout = 60000 # Timeout in millis for a connection to stay idle in the pool
#maxRetry = 2 # Number of times that a request should be tried again
#requestTimeout = 60000 # Timeout in millis for performing an HTTP request
#enableSni = true # When set to true, enable Server Name indication (SNI)
#enableHostnameVerification = false # When set to true, enable hostname verification: SSLEngine.setHttpsEndpointIdentificationAlgorithm("HTTPS")
#useInsecureTrustManager = true # Use an insecure TrustManager that trusts all server certificates
#filterInsecureCipherSuites = true # Turn to false to not filter out insecure and weak cipher suites
#sslEnabledProtocols = [TLSv1.2, TLSv1.1, TLSv1] # Array of enabled protocols for HTTPS, if empty use the JDK defaults
#sslEnabledCipherSuites = [] # Array of enabled cipher suites for HTTPS, if empty use the AHC defaults
#sslSessionCacheSize = 0 # SSLSession cache size, set to 0 to use JDK's default
#sslSessionTimeout = 0 # SSLSession timeout in seconds, set to 0 to use JDK's default (24h)
#disableSslSessionResumption = false # if true, SSLSessions won't be resumed
#useOpenSsl = true # if OpenSSL should be used instead of JSSE
#useNativeTransport = false # if native transport should be used instead of Java NIO (requires netty-transport-native-epoll, currently Linux only)
#enableZeroCopy = true # if zero-copy upload should be used if possible
#tcpNoDelay = true
#soReuseAddress = false
#allocator = "pooled" # switch to unpooled for unpooled ByteBufAllocator
#maxThreadLocalCharBufferSize = 200000 # Netty's default is 16k
}
dns {
#queryTimeout = 5000 # Timeout in millis of each DNS query in millis
#maxQueriesPerResolve = 6 # Maximum allowed number of DNS queries for a given name resolution
}
}
jms {
#replyTimeoutScanPeriod = 1000 # scan period for timedout reply messages
}
data {
#writers = [console, file] # The list of DataWriters to which Gatling write simulation data (currently supported : console, file, graphite, jdbc)
console {
#light = false # When set to true, displays a light version without detailed request stats
#writePeriod = 5 # Write interval, in seconds
}
file {
#bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes
}
leak {
#noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening
}
graphite {
#light = false # only send the all* stats
#host = "localhost" # The host where the Carbon server is located
#port = 2003 # The port to which the Carbon server listens to (2003 is default for plaintext, 2004 is default for pickle)
#protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp")
#rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite
#bufferSize = 8192 # Internal data buffer size, in bytes
#writePeriod = 1 # Write period, in seconds
}
}
}

Shelfy.scala

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package kujilabo

package computerdatabase

import io.gatling.core.Predef._
import io.gatling.http.Predef._

import scala.concurrent.duration._

class Shelfy extends Simulation {

val httpProtocol = http
.baseUrl("http://localhost:8080")
.acceptHeader("""text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8""")
.acceptEncodingHeader("""gzip, deflate""")
.acceptLanguageHeader("""en-gb,en;q=0.5""")
.userAgentHeader("""Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:31.0) Gecko/20100101 Firefox/31.0""")

val computerDbScn = scenario("Shelfy Scenario")
.exec(http("getIndex")
.get("/index.html")
.check(status is 200))


setUp(computerDbScn.inject(
constantUsersPerSec(10) during 1.minute
).protocols(httpProtocol))
}

このコードの意味は、http://localhost:8080/index.html に対して1秒間あたり10回のリクエストを送るのを1分間続ける、です。

実行する

以下のコマンドで実行します。

1
sbt gatling:test

結果はtarget/gatling 以下のディレクトリに作成されます。index.htmlを開いてみてください。
こんな感じのグラフが表示されます。

以上です。