負荷テストツールGatling

Yuki Furusawa
nextbeat-engineering
14 min readDec 19, 2023
Gatling

◾️はじめに

こんにちは。2023年9月にネクストビート(NB)へ入社した古沢です。

現在は保育士バンク!のプロジェクトマネージャー(PjM)としてスクラムチームに所属しています。

今回は負荷テストツールのGatlingについて記載します。

まず、エンジニアではなくPjMの私が何故Gatlingの記事を書くに至ったかご説明します。

私は前職で人材紹介サービスの事業会社にて、バックエンドエンジニア兼スクラムマスターとして働いていました。主に使っていた言語はJavaでした。それ以前も含め長年Javaを使っていたため、Javaが好きで今でもコミュニティイベントに参加しています。

先日開催されたJJUG CCC 2023 Fallにも現地参加して、色々なセッションを聴講し良い学びになりました。

JJUG CCC 2023 Fall

https://ccc2023fall.java-users.jp/

その中でも特に興味深かった「Gatlingによる負荷テスト入門」というセッションにて、「Gatling」の存在を知ったため今回記事を書こうと思い至りました。

「Gatlingによる負荷テスト入門」

irofさん

https://speakerdeck.com/irof/gatlingniyorufu-he-tesutoru-men

◾️Gatlingとは

前置きが長くなりましたが、Gatlingの概要について説明します。

Gatlingとは、2012年に公開された負荷テストのフレームワークです。GUIでブラウザ操作を記録する機能もありますが、メインとしてはDSL(Domain Specific Language)で負荷試験のシナリオを記述できる所が特徴です。DSLなので基本的にはエンジニア(プログラマ)が記述し管理することを前提にしたものになります。

(チュートリアルのサンプル)

使用できる言語は、以前はScalaのみでしたが2021年にJavaとKotlinにも対応しました。

公式のチュートリアルを参考にしながら、ローカル環境での導入と簡易的な負荷テストシナリオの実行までを試してみます。

◾️Gatlingの導入

0. 環境

下記の端末を使用しています。

  • MacBook Pro
  • Intel Core
  • macOS Venture

1. JDKをインストール

Gatling自体はJavaで作られているため実行環境としてJDKが必要です。

どのような形式でも良いのでJDKをインストールしたら、バージョン確認しておきます。

今回はAmazon Correttoの1.8.0_382を使用します。

java -version

2. Gatlingをインストール

公式サイトからGatlingのzipファイルをダウンロードします。

今回はコミュニティ版の3.9.5を使用します。

  • gatling-charts-highcharts-bundle-3.9.5-bundle.zip

zipファイルを解凍し任意の場所におきます。

3. 動作確認

解凍した場所に移動し、bin配下のgatling.shを実行します。

./bin/gatling.sh

下記のような内容が表示されたらOKです。今は0を入力し終了させましょう。

Do you want to run the simulation locally, on Gatling Enterprise, or just package it?
Type the number corresponding to your choice and press enter
[0] <Quit>
[1] Run the Simulation locally
[2] Package and upload the Simulation to Gatling Enterprise Cloud, and run it there
[3] Package the Simulation for Gatling Enterprise
[4] Show help and exit

あっと言う間に導入が完了しました!

※今回は簡易的なお試しをするためzipを解凍するだけのbundle形式としましたが、実践ではbuildツール(Maven/Gradle/SBT)でのプラグイン形式の方が適切かもしれません。

◾️負荷テストシナリオのレコード機能

レコーダーを起動します。下記のようなGUIが立ち上がります。

./bin/recorder.sh
recoderの設定(デフォルト)

チュートリアルの記述も参考にしながら数箇所変更します。

①Simulation Information_Package:任意のパッケージ名を記載(テストシナリオの出力パッケージ)今回はgatling.sample

②Simulation Information_Format:Scala(※NBのプロダクトではJavaは使っておらず、Scalaを主に利用しているため合わせています。)

③Filters_DenyList:「No static resources」ボタンを押します

④Save preferences:チェックを入れます

recoderの設定(変更後)

「Start !」ボタンを押す前に重要な設定があります。

Network_localhost HTTP/HTTPSで設定したポート番号(デフォルトでは8000)に合わせて、PCのプロキシ設定を行います。

Macでのプロキシ設定

「Start !」ボタンを押すと下記のような画面になり、ブラウザ操作を記録中の状態になります。(ブラウザはSafariを使用)

記録開始

この状態で、例えば「保育士バンク!」のWebサイト(※本番環境ではなく、localhostで立ち上げた環境を使います)を操作するとEventsに記録されます。「Stop & Save」ボタンを押すことでシナリオがScalaのコードで出力されます。

保育士バンク!
ブラウザ操作が記録された

設定時に指定した場所にシナリオのファイルが出力されます。

./user-files/simulations/gatling/sample/BasicSimulation.scala
出力されたシナリオ抜粋(Scala)

次に、このシナリオを実行します。

./bin/gatling.sh

①1を入力します([1] Run the Simulation locally)

②先ほど出力したシナリオの番号を入力します([1] gatling.sample.BasicSimulation)

③Select run description (optional) では何も入力せずreturnキーを押します

Gatlingが実行されます!

(先ほどのレコード機能で出力されたシナリオでは、setUpにてatOnceUsers(1):「同時アクセスのユーザー数1」と指定されているはずなので、負荷は基本掛からないです。)

コンソールにOKとなっているリクエストは問題なく処理された数で、KOはノックアウトしてしまった数になります。

> request_0                                        (OK=1      KO=0     )
> request_0 Redirect 1 (OK=1 KO=0 )
> request_3 (OK=1 KO=0 )
> request_5 (OK=1 KO=0 )
> request_13 (OK=1 KO=0 )
> request_15 (OK=1 KO=0 )
> request_6 (OK=1 KO=0 )
> request_2 (OK=1 KO=0 )

Gatlingの実行結果がHTML形式で出力されます。

./results/basicsimulation-タイムスタンプ/index.html
Gatling実行結果レポート

上記では負荷はかけていない状態になりますが、ブラウザ操作をレコードしてシナリオを出力し、Gatling実行・結果レポートを見るまでの基本的な機能が分かりました。

◾️DSLで負荷テストシナリオを自分で書く

レコード機能で出力されたBasicSimulation.scalaをベースに、自分で負荷テストのシナリオを書いてみます。

例えば、

保育士バンク!のWebサイトトップページ

→求人検索のトップ画面

→東京都を選択し東京の求人検索結果

を表示するまでのシナリオを書いてみます。

画面遷移ごとに1秒ポーズを入れる場合の記述は下記の通りです。

package gatling.sample

import scala.concurrent.duration._

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

class CustomSimulation extends Simulation {

private val httpProtocol = http.baseUrl("http://localhost:3000")

private val scn = scenario("トップ画面から求人検索→東京都の求人を検索する:負荷は画面遷移時1秒ポーズ、1人同時実行")
.exec(http("トップ画面").get("/"))
.pause(1)
.exec(http("求人検索トップ画面").get("/search"))
.pause(1)
.exec(http("東京都の求人検索結果").get("/tokyo"))

setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
}

コードの解説はしなくとも直感的に読み取れるのではないでしょうか?

実行方法は前と同様です。

./bin/gatling.sh

コンソール

---- Requests ------------------------------------------------------------
> Global (OK=3 KO=0 )
> トップ画面 (OK=1 KO=0 )
> 求人検索トップ画面 (OK=1 KO=0 )
> 東京都の求人検索結果 (OK=1 KO=0 )

実行結果レポート

./results/basicsimulation-タイムスタンプ/index.html
DSLシナリオ実行結果レポート

このシナリオを一部修正し負荷を設定します。

1秒間隔だと長いので、pauseを削除します。

scn.inject(atOnceUsers(1))「同時アクセスのユーザー数1」:この部分をユーザー数100にしてみます。

package gatling.sample

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

class CustomSimulation extends Simulation {

private val httpProtocol = http.baseUrl("http://localhost:3000")

private val scn = scenario("トップ画面から求人検索→東京都の求人を検索する:負荷は100人同時実行")
.exec(http("トップ画面").get("/"))
.exec(http("求人検索トップ画面").get("/search"))
.exec(http("東京都の求人検索結果").get("/tokyo"))

setUp(scn.inject(atOnceUsers(100))).protocols(httpProtocol)
}

※絶対に本番環境向けで実行しないように注意して下さい!

Gatlingを実行した結果、やはり一部ノックアウトしました・・・

---- Requests -------------------------------------------------------------
> Global (OK=292 KO=8 )
> トップ画面 (OK=100 KO=0 )
> 求人検索トップ画面 (OK=100 KO=0 )
> 東京都の求人検索結果 (OK=92 KO=8 )

実行結果レポート

リクエストごとの詳細も確認可能です。

Gatlingを使って100ユーザー同時リクエストの負荷をかけた結果、以下のことが分かりました。

  • 8件のfailedが確認できました
  • 1ユーザーで実行した時と比べて、レスポンスタイムが長くなっていることが確認できました
  • リクエストのfailedはありましたが、localhostのサーバーがダウンすることはありませんでした
  • failedの原因についてはレポートからは情報が得られず、アプリケーションのログを見る必要がありました

以上、非常にシンプルなシナリオでしたが、Gatlingを使って負荷をかけ、その結果を確認する方法を試してみました。

その他の色々なシナリオや負荷を記述する場合は、公式ドキュメント調べながら実装することが出来そうです。

https://gatling.io/docs/gatling/reference/current/

◾️おわりに

負荷テストは機会がないとなかなか関わることが少なく、何となく難しそうと思われがちですが、Gatlingを使うと簡単に分かりやすく負荷をかけてどうなるかをテスト出来そうだなという印象を受けました。

今回試した範囲だと簡易的なことのみ行なっているため、実際のプロダクトの負荷テストに利用すると、課題点などあるかもしれません。ですが、少なくとも導入は非常に楽(JDK環境さえあれば、zipを解凍するだけ)に出来るため、負荷テストツールの導入検討時の候補としては挙げやすいものかなと思いました。

DSLがメインとなるため、プロダクトコードと一緒に管理することもでき非常にエンジニア寄りな所も強みになります。実行結果レポートも綺麗で見やすいなという印象です。

今回の記事を書くきっかけとなった、JJUG CCCのセッション「Gatlingによる負荷テスト入門」のGoalsとして「セッションを聞いた後で、ちょっとやってみた。を共有する」ことが掲げられていたため、本記事を書くことでGoalsの達成ができました。

技術コミュニティのイベントではこういった考え方を大事にしたいなと私も常に思っており、今後も社外で得た学びはテックブログや社内LT会などで共有していきたいと思っています。

We are hiring!

本記事をご覧いただき、ネクストビートの技術や組織についてもっと話を聞いてみたいと思われた方、カジュアルにお話しませんか?

・今後のキャリアについて悩んでいる
・記事だけでなく、より詳しい内容について知りたい
・実際に働いている人の声を聴いてみたい

など、まだ転職を決められていない方でも、ネクストビートに少しでもご興味をお持ちいただけましたら、ぜひカジュアルにお話しましょう!

🔽申し込みはこちら
https://hrmos.co/pages/nextbeat/jobs/1000008

また、ネクストビートについてはこちらもご覧ください。

🔽エントランスブック
https://note.nextbeat.co.jp/n/nd6f64ba9b8dc

--

--