動機・背景
- Webサービスのバックエンドで利用するAPIの負荷テストを行いたい
-
Gatlingというツールが良さそうだったので使ってみた備忘録
- PythonベースのLocustは以前使ったことがあったので今回は別のものを
対象読者
- 開発したAPIの負荷テストを実施したい方
検証環境
ホスト環境
- CentOS 7.4.1708
- Docker 18.09.3
- Gatling 3.2.1 (Scala 2.12)
準備
Docker
公式?のDockerイメージを使います。
Scala
Dockerを使うのでローカル環境でScalaを用意しなくても何とかなりますが、Intellij で SCALA を始めるなどに沿って環境を準備しておくと、コードの確認等がスムーズです。
sbt-based Scala projectを作成します。
コード
csvファイルから読み込んだデータをランダムに流し込んでAPIのエンドポイントをテストするサンプルコードです。
データ
src/main/resources/data/search.csv
cookie,query
cookie 1,test
cookie 2,iPhone SE
cookie 3,wallet
cookie 4,scarf
cookie 3,banana
cookie 2,men's shoes
cookie 1,socks
cookie 5,microSD
Scalaコード
- ビジネスプロセスごとにobject(Scalaのシングルトン)に分割しておくと見通しがよくコードの再利用もしやすくなります
-
constantUsersPerSec
,rampUsersPerSec
,nothingFor
などのDSLを使って、定義したシナリオにユーザを注入していきます。- 一定数のユーザを注入したり、注入するユーザの数を徐々に増やしたり
src/main/scala/template/LoadTest.scala
package template
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class LoadTest extends Simulation {
val feeder = csv("search.csv").random
val httpProtocol = http
.baseUrl("http://example.com")
.acceptHeader("application/json")
.connectionHeader("keep-alive")
object Search1 {
val search = feed(feeder)
.exec(addCookie(Cookie("cookie", "${cookie}")))
.exec(http("Search1")
.get("/api/v1/search1")
.queryParam("query", "${query}")
.header("Keep-Alive", "150")
.header("Content-Type", "application/json")
)
}
object Search2 {
val search = feed(feeder)
.exec(addCookie(Cookie("cookie", "${cookie}")))
.exec(http("Search2")
.get("/api/v1/search2")
.queryParam("query", "${query}")
.header("Keep-Alive", "150")
.header("Content-Type", "application/json")
)
}
def run(): Unit = {
val scenarioSearch1 = scenario("scenario Search1")
.exec(Search1.search)
val scenarioSearch2 = scenario("scenario Search2")
.exec(Search2.search)
val stepInjections = Seq(
nothingFor(5 seconds),
constantUsersPerSec(1) during (3 seconds),
constantUsersPerSec(2) during (3 seconds),
constantUsersPerSec(3) during (3 seconds),
constantUsersPerSec(4) during (3 seconds),
constantUsersPerSec(3) during (3 seconds),
constantUsersPerSec(2) during (3 seconds),
constantUsersPerSec(1) during (3 seconds)
)
val waveInjections = Seq(
nothingFor(5 seconds),
rampUsersPerSec(1) to 4 during (9 seconds),
rampUsersPerSec(4) to 1 during (9 seconds)
)
setUp(
// will be tested in parallel
scenarioSearch1.inject(stepInjections),
scenarioSearch2.inject(waveInjections)
)
}
run()
}
実行は、こんなイメージ。
存在しないAPIなのでこのままでは動作確認できないですが...
run.sh
# !/bin/sh
if [ $# -ne 0 ]; then
echo "No arguments accepted."
exit 1
fi
mkdir -p "$PWD/results"
docker run -it --rm \
-v $PWD/src/main/resources/opt/gatling/user-files/resources \
-v $PWD/src/main/scala:/opt/gatling/user-files/simulations \
-v $PWD/results:/opt/gatling/results \
denvazh/gatling:3.2.1
まとめ
Scalaベースの負荷テストツールGatlingを試したので、備忘録としてサンプルコードとともに紹介しました。
負荷テストをコードとして残しておけるのは便利ですね。
チートシートがあるのはありがたいですが、そこから詳しいコード例に飛べないのが玉にキズだなと思いました。