最近ちょっと目にした負荷テストツール、Gatlingをちょっと試してみました。
Gatling
http://gatling-tool.org/
Apache JMeterのような負荷テストツールらしいのですが、
みたいな特徴があるみたいです。パフォーマンスが良いという話もあるらしいのですが、最近はJMeterも頑張っているそうです。
自分としては、普段こういう負荷テストツールは使っていない(JMeter面倒そうだし…)ので、DSLで書けるようなツールは魅力的ですね。
1系と開発中の2系があるみたいで、今回は2系を使うことにします。
ドキュメントとしてはWikiを見るのですが…
User Document
https://github.com/excilys/gatling/wiki
内容的には、1系の書き方が混じっているっぽいので、そのあたりはダウンロードしたファイルについてくるサンプルを見ながら読み替えていくのがよいでしょう。
参照したドキュメントは、以下になります。
Getting Started
https://github.com/excilys/gatling/wiki/Getting-Started
First Steps with Gatling
https://github.com/excilys/gatling/wiki/First-Steps-with-Gatling
日本語のサイトでは、こちらが非常に参考になりました。
負荷テストツール「Gatling」を使ってみよう。
http://blog.udcp.net/2013/10/07/gatling-stress-tool/
インストール
では、まずはGatlingをインストールします。事前に要求されるのは、JDKがインストールされていることです。あとは、アーカイブをダウンロードしてきて展開するだけ。
$ tar -zxvf gatling-charts-highcharts-2.0.0-M3a-bundle
.tar.gz
今回はtar.gzをダウンロードし、バージョンは2.0.0-M3aを選択しました。
インストールは、これだけです。
あと、サンプルプログラムが
gatling-charts-highcharts-2.0.0-M3a/user-files/simulations
ディレクトリ配下に入っているので、目を通すとよいでしょう。
こんな感じです。
$ find gatling-charts-highcharts-2.0.0-M3a/user-files/simulations/ -type f gatling-charts-highcharts-2.0.0-M3a/user-files/simulations/basic/BasicExampleSimulation.scala gatling-charts-highcharts-2.0.0-M3a/user-files/simulations/advanced/SomeOtherScenario.scala gatling-charts-highcharts-2.0.0-M3a/user-files/simulations/advanced/SomeScenario.scala gatling-charts-highcharts-2.0.0-M3a/user-files/simulations/advanced/Headers.scala gatling-charts-highcharts-2.0.0-M3a/user-files/simulations/advanced/AdvancedExampleSimulation.scala
シナリオを書いてみる
では、負荷テストシナリオを書いてみましょう。テスト対象は…手元に手頃なものがなかったので、まずはJBoss AS 7のトップページにしました。
$ jboss-as-7.1.1.Final/bin/standalone.sh
作成するシナリオは、以下のディレクトリ配下にScalaソースコードとして作成します。
gatling-charts-highcharts-2.0.0-M3a/user-files/simulations
今回は、こんなシナリオを作成しました。
gatling-charts-highcharts-2.0.0-M3a/user-files/simulations/GettingStartedSimulation.scala
import io.gatling.core.Predef._ import io.gatling.http.Predef._ import io.gatling.jdbc.Predef._ import io.gatling.http.Headers.Names._ import scala.concurrent.duration._ import bootstrap._ import assertions._ class GettingStartedSimulation extends Simulation { val httpProtocol = http .baseURL("http://localhost:8080") .acceptCharsetHeader("ISO-8859-1,utf-8;q=0.7,*;q=0.7") .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") .acceptEncodingHeader("gzip, deflate") .acceptLanguageHeader("fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3") .disableFollowRedirect val scn = scenario("Getting Started Scenario") .exec { http("simpleRequest") .get("/") .check(status.is(200)) } setUp(scn.inject(ramp(1000 users) over (50 seconds))) .protocols(httpProtocol) .assertions(global.successfulRequests.percent.is(100)) }
単純に、トップページにアクセスするシナリオです。ステータスコードが200であることを、シナリオ中で定義しています。
シナリオは、作成したScalaのクラス名で実行時に選びます。また、
http("simpleRequest")
で付けた名前が、結果レポートに現れます。
負荷は、1000人のユーザが50秒でかけていきます。つまり、秒20人。そして、リクエストはひとりあたり「http://localhost:8080/」への1回なので、計1000回のリクエストが実行されるということになります。
setUp(scn.inject(ramp(1000 users) over (50 seconds))) .protocols(httpProtocol) .assertions(global.successfulRequests.percent.is(100))
assertionsはなくてもいいみたいですが、100%成功リクエストが受け取れていること、を入れておきました。
実行する
それでは、書いたシナリオを実行してみます。
$ gatling-charts-highcharts-2.0.0-M3a/bin/gatling.sh GATLING_HOME is set to /xxxxx/gatling-charts-highcharts-2.0.0-M3a
作成したScalaソースコードのコンパイルが行われるようで、けっこう重たいです…。また、コンパイルできないシナリオを入れてしまうと、例外を投げてコケてしまいます。
で、起動するとシナリオを選択するように聞かれるので
Choose a simulation number: [0] GettingStartedSimulation [1] TransitionSimulation [2] advanced.AdvancedExampleSimulation [3] basic.BasicExampleSimulation
ここでは、「0」と入力。
*[1]と出ているのは、後で作成したシナリオです…
0
あとはEnterを押していくと
Select simulation id (default is 'gettingstartedsimulation'). Accepted characters are a-z, A-Z, 0-9, - and _ Select run description (optional) Simulation GettingStartedSimulation started...
シナリオが実行されます。
================================================================================ 2013-12-28 18:46:04 0s elapsed ---- Getting Started Scenario -------------------------------------------------- [ ] 0% waiting: 1000 / running: 0 / done:0 ---- Requests ------------------------------------------------------------------ > Global (OK=0 KO=0 ) ================================================================================
進捗状況がこのまま表示されていき、終了するとこんなレポートが出ます。
Simulation finished. Parsing log file(s)... Parsing log file(s) done Global percentage of requests OK is equal to 100 : true Simulation successful. Generating reports... ================================================================================ ---- Global Information -------------------------------------------------------- > numberOfRequests 1000 (OK=1000 KO=0 ) > minResponseTime 0 (OK=0 KO=- ) > maxResponseTime 1010 (OK=1010 KO=- ) > meanResponseTime 16 (OK=16 KO=- ) > stdDeviation 84 (OK=84 KO=- ) > percentiles1 20 (OK=20 KO=- ) > percentiles2 500 (OK=500 KO=- ) > meanNumberOfRequestsPerSecond 20 (OK=20 KO=- ) ---- Response Time Distribution ------------------------------------------------ > t < 800 ms 996 ( 99%) > 800 ms < t < 1200 ms 4 ( 0%) > t > 1200 ms 0 ( 0%) > failed 0 ( 0%) ================================================================================ Reports generated in 0s. Please open the following file : /xxxxx/gatling-charts-highcharts-2.0.0-M3a/results/gettingstartedsimulation-20131228184602/index.html
最後に、レポートがファイルに出たよと言っているので
Please open the following file : /xxxxx/gatling-charts-highcharts-2.0.0-M3a/results/gettingstartedsimulation-20131228184602/index.html
見てみます。
リクエストに付けた名前(今回は「simpleRequest」)を選択すると、そのリクエストに特化した情報も見れます。
すごい…。
その他、同ディレクトリにログやコンソールに出力された情報もファイルとしてできているので、確認するといいでしょう。
simulation.log stats.tsv
シナリオ中で複数のリクエストを実行する
今度は、ひとつのシナリオで複数のリクエストを実行してみます。
gatling-charts-highcharts-2.0.0-M3a/user-files/simulations/TransitionSimulation.scala
import io.gatling.core.Predef._ import io.gatling.http.Predef._ import io.gatling.jdbc.Predef._ import io.gatling.http.Headers.Names._ import scala.concurrent.duration._ import bootstrap._ import assertions._ class TransitionSimulation extends Simulation { val httpProtocol = http .baseURL("http://localhost:8080") .acceptCharsetHeader("ISO-8859-1,utf-8;q=0.7,*;q=0.7") .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") .acceptEncodingHeader("gzip, deflate") .acceptLanguageHeader("fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3") .disableFollowRedirect val scn = scenario("Transition Simulation") .repeat(5) { exec { http("indexRequest") .get("/") .check(status.is(200)) }.pause(0 milliseconds, 100 milliseconds) }.exec { http("documentationRequest") .get("/documentation.html") .check(status.is(200)) } setUp(scn.inject(ramp(1000 users) over (50 seconds))) .protocols(httpProtocol) .assertions(global.successfulRequests.percent.is(100)) }
アクセス先は、やっぱりJBoss AS 7のトップページと、そこから辿れる「documentation.html」にしました…。
トップページには5回アクセスし、その後ドキュメントページにアクセスします。また、ユーザー数は1000人が50秒かけてアクセスしてくるので、6000リクエストが実行されることになりますね。
で、今回は1を選択。
Choose a simulation number: [0] GettingStartedSimulation [1] TransitionSimulation [2] advanced.AdvancedExampleSimulation [3] basic.BasicExampleSimulation 1
さっき、最初のシナリオを書いた時に見えていたのは、これです…。
結果は、このように。
Simulation finished. Parsing log file(s)... Parsing log file(s) done Global percentage of requests OK is equal to 100 : true Simulation successful. Generating reports... ================================================================================ ---- Global Information -------------------------------------------------------- > numberOfRequests 6000 (OK=6000 KO=0 ) > minResponseTime 0 (OK=0 KO=- ) > maxResponseTime 110 (OK=110 KO=- ) > meanResponseTime 4 (OK=4 KO=- ) > stdDeviation 6 (OK=6 KO=- ) > percentiles1 10 (OK=10 KO=- ) > percentiles2 20 (OK=20 KO=- ) > meanNumberOfRequestsPerSecond 119 (OK=119 KO=- ) ---- Response Time Distribution ------------------------------------------------ > t < 800 ms 6000 (100%) > 800 ms < t < 1200 ms 0 ( 0%) > t > 1200 ms 0 ( 0%) > failed 0 ( 0%) ================================================================================ Reports generated in 0s. Please open the following file : /xxxxx/gatling-charts-highcharts-2.0.0-M3a/results/transitionsimulation-20131228190301/index.html
リクエストごとに確認できます。
indexRequest
documentationRequest
なかなか便利です。他にも、シナリオをまとめて実行することもできるみたいです。詳しくは、サンプルを…。