ã¯ããã«
ä»ãŸã§ã¯ JMeter ã§ããè² è·ãã¹ããè¡ã£ãããšãªãã£ãã®ã§ãããæè¿ PlayFab 㧠CloudFunction ã®è² è·ãã¹ããè¡ãéã« Gatling ãåããŠå©çšããŸããã
ä»åã®è² è·ãã¹ãã§ã¯ãåãŠãŒã¶æ¯ã®ã¬ãŒããªãããã®å¶éçãèæ ®ããå®å©çšæãæ³å®ãã圢ã§è¡ãããšãèŠæ±ããããããåäžãŠãŒã¶ã®èªèšŒæ å ±ã䜿ãåãããšã¯æãŸãããªããšèããŸãããããã§ãè€æ°ã®èªèšŒæžã¿ãŠãŒã¶ã®æ å ±ãå ã« PlayFab ã® CloudFunction ã®è² è·ãã¹ããå®æœããã®ã§ãããè¥å¹²å®è£ ã«èŠæŠããããæé ã«ã€ããŠèšäºãšããŠæ®ããŠããããšã«ããŸããã
ãŸããæ¬èšäºã§ã¯ Gatling ã®ã»ããã¢ããããèšèŒããŠããŸããã該åœã³ãŒãããã®èª¬æãæ©ãèŠãããšããæ¹ã¯ è€æ°ãŠãŒã¶èªèšŒãè¡ããã¹ãã·ããªãªãå®è£
ãã
é
ç®ããåç
§ãã ããã
åäœç°å¢
- macOS Big Sur
- Java OpenJDK 12.0.1
- æªã€ã³ã¹ããŒã«ã®æ¹ã¯äºåã« å ¬åŒãµã€ããã OpenJDK ãã€ã³ã¹ããŒã«ããŠãã ãã
Gatling ã®ç°å¢ãæŽãã
Gatling ã«ã¯ 2 çš®é¡ã®ã»ããã¢ããæ¹æ³ãçšæãããŠããŸãã ã¹ã¿ã³ãã¢ããŒã³ãªããŒã«ãçŽæ¥å ¬åŒãµã€ãããããŠã³ããŒãããããMaven ã sbt ãšãã£ãããŒã«çµç±ã§ããŠã³ããŒããããéžæã§ããŸãã
ã©ã¡ãã®æ¹æ³ã§ã»ããã¢ãããããã«ã€ããŠã§ãããæ°èŠã§ãã¹ãã±ãŒã¹ã Gatling ã§æžããŠããçšéã ãšåè ã«ãªããæ¢åã®ãããžã§ã¯ãã« Gatling ãåã蟌ãçšéã ãšåŸè ã«ãªãããšåããŸãã
æ¬èšäºã§ã¯ãåè ã®ã¹ã¿ã³ãã¢ããŒã³ãªããŒã«ãçŽæ¥å ¬åŒãµã€ãããããŠã³ããŒãããæ¹æ³ã§ Gatling ã®ç°å¢ãã»ããã¢ããããŸãã
å ¬åŒãµã€ããã Gatling ãããŠã³ããŒããã
Gatling ã®ãããããŒãž ã«é·ç§»ããŠãããŒãžã 2 Ways to use Gatling
ã®é
ç®ãŸã§ã¹ã¯ããŒã«ããåŸãããŠã³ããŒããã¿ã³ãã¯ãªãã¯ããŸãã
DOWNLOAD GATLING'S BUNDLE
ã«ãã DOWNLOAD NOW
ãã¿ã³ãã¯ãªãã¯ãã
ãã¡ã€ã«ããŠã³ããŒãåŸã¯ããŠã³ããŒããã zip ãã¡ã€ã«ãé©åœãªãã©ã«ãã«å±éããŠé
眮ããŸãã
æ©éã¿ãŒããã«ã§å±éãããã©ã«ãå
ã«ãã ./bin/gatling.sh
ãå®è¡ããŠãæ£åžžã«ã³ãã³ããå®è¡ã§ããã確èªããŠã¿ãŸãã
OS ã Windows ã®å Žå㯠./bin/gatling.bat
ãå®è¡ããŸãã
âš ./bin/gatling.sh ~/D/gatling-charts-highcharts-bundle-3.5.1
GATLING_HOME is set to /Users/nika/Desktop/gatling-charts-highcharts-bundle-3.5.1
Choose a simulation number:
[0] computerdatabase.BasicSimulation
[1] computerdatabase.advanced.AdvancedSimulationStep01
[2] computerdatabase.advanced.AdvancedSimulationStep02
[3] computerdatabase.advanced.AdvancedSimulationStep03
[4] computerdatabase.advanced.AdvancedSimulationStep04
[5] computerdatabase.advanced.AdvancedSimulationStep05
0 # å®è¡ããããã¹ãã®çªå·ãå
¥åãããä»åã¯é©åœã« 0 ãæå®
Select run description (optional)
# å®è¡ãããã¹ãã«é¢ãã説ææãå
¥åãããäœãå
¥åããå
容ãç¡ã or
# 説ææã®å
¥åãå®äºããã Enter ãå
¥åããŠãå®éã«ãã¹ããå®è¡ãã
# éžæãããã¹ãã®å®è¡ãéå§ãã
# (0 ãå
¥åããã®ã§ computerdatabase.BasicSimulation ãå®è¡ããã)
Simulation computerdatabase.BasicSimulation started...
#...
Simulation computerdatabase.BasicSimulation completed in 26 seconds
Parsing log file(s)...
Parsing log file(s) done
Generating reports...
# ãã¹ãã®å®è¡ãç¡äºå®äºãããšãçµæã衚瀺ããã¬ããŒããã¡ã€ã«ãçæãããã
# ã¬ããŒãçæå
ã®ãã¡ã€ã«ãã¹ã¯å®è¡çµæã®æ«å°Ÿã«è¡šç€ºãããã
# ã¬ããŒããã¡ã€ã«ã¯ HTML ã§çæããããããé©åœãªãã©ãŠã¶ã§éãããšã§å
容ã確èªããããšãåºæ¥ãã
================================================================================
---- Global Information --------------------------------------------------------
> request count 13 (OK=13 KO=0 )
> min response time 230 (OK=230 KO=- )
> max response time 483 (OK=483 KO=- )
> mean response time 324 (OK=324 KO=- )
> std deviation 98 (OK=98 KO=- )
> response time 50th percentile 259 (OK=259 KO=- )
> response time 75th percentile 415 (OK=415 KO=- )
> response time 95th percentile 476 (OK=476 KO=- )
> response time 99th percentile 482 (OK=482 KO=- )
> mean requests/sec 0.481 (OK=0.481 KO=- )
---- Response Time Distribution ------------------------------------------------
> t < 800 ms 13 (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: /Users/nika/Desktop/gatling-charts-highcharts-bundle-3.5.1/results/basicsimulation-20210314133324259/index.html
./bin/gatling.sh
ãå®è¡ããåŸãäžèšã®ãããªåºåã確èªã§ããã°ãåé¡ãªãã¹ã¿ã³ãã¢ããŒã³çã® Gatling ç°å¢ã®ã»ããã¢ãããå®äºããŠããŸãã
ãŸããè² è·ãã¹ãã®ã¬ããŒãã確èªãããå Žåã¯ãåºåçµæã«ãã Please open the following file: <ã¬ããŒãã®ãã¡ã€ã«ãã¹>
ã«èšèŒãããŠãããã¡ã€ã«ããã©ãŠã¶ã§éããŸãã
html æ¡åŒµåãéãã¢ããªã®ããã©ã«ããäœããã®ãã©ãŠã¶ã«ãªã£ãŠããã®ã§ããã°ãã¿ãŒããã«ãã open <ã¬ããŒãã®ãã¡ã€ã«ãã¹>
ãå®è¡ããã®ã§ãæ§ããŸããã
Gatling ã§ãã¹ãã·ããªãªãå®è£ ãã
Gatling ã®ãã¹ãã·ããªãªãæžãå Žæ㯠./user-files/simulations
ãã©ã«ãå
ã«ãªããŸãã ãã¹ãã·ããªãªã Scala ã§æžããåŸããã¡ã€ã«ã ./user-files/simulations
ãã©ã«ãã«é
眮ããŸãããããšã./bin/gatling.sh
ãå®è¡ããéã®å®è¡ãããã¹ãã·ããªãªã®ãªã¹ãã«åºãŠããããã«ãªããŸãã
ç°¡åãªãã¹ãã·ããªãªãè©Šãã«æžããŠã¿ã
ãŸãã¯è©Šãã«ç§ã®ããã°ã«å¯ŸããŠã®ã¢ã¯ã»ã¹è² è·ãèšæž¬ããããã®ãã¹ããå®è£
ããŠãããŸãã./user-files/simulations
ãã©ã«ãå
ã« nikaera.com
ãã©ã«ããäœæããAccessSimulation.scala
ãšããè² è·ãã¹ãã®ã·ããªãªãã¡ã€ã«ãäœæããŸãã
// ./user-files/simulations/nikaera.com/AccessSimulation.scala
package com.nikaera
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.collection.mutable.ListBuffer
import io.gatling.core.structure.PopulationBuilder
// 1. Simulation ã¯ã©ã¹ãç¶æ¿ããŠãã¹ãã·ããªãªãå®è¡ããã¯ã©ã¹ãå®çŸ©ãã
class AccessSimulation extends Simulation {
// 2. HTTP ã¢ã¯ã»ã¹ããéã®èšå®å€ãå
¥åããã
// ä»åã¯ã¢ã¯ã»ã¹å
ã®ããŒã¹ URL ãå®çŸ©ããããã® baseUrl ã®ã¿æå®
val httpConf = http
.baseUrl("https://nikaera.com")
// 3. Scala ã® ListBuffer ãçšããŠè€æ°ã·ããªãªãæ ŒçŽãã scenarios å€æ°ãçšæãã
val scenarios = new ListBuffer[PopulationBuilder]()
// 4. httpConf ã§èšå®ããæ
å ±ãå
ã« / (https://nikaera.com) åã³
// /tech/ (https://nikaera.com/tech/) ãžåæ 10 ã¢ã¯ã»ã¹ããã®ãã
// 5ç§æ¯ã« 3åå®è¡ããã·ããªãªãäœæããŠãscenarios å€æ°ã«æ ŒçŽãã
val pollingApiScn = scenario("Polling Simulation")
.exec(
http("Top Page")
.get("/")
.check(status.is(200))
)
.exec(
http("Tech Page")
.get("/tech/")
.check(status.is(200))
)
scenarios += pollingApiScn
.inject(
atOnceUsers(10),
nothingFor(5 seconds),
atOnceUsers(10),
nothingFor(5 seconds),
atOnceUsers(10)
)
.protocols(httpConf);
// 5. 4. ã§å®çŸ©ããã·ããªãªãå®è¡ã㊠https://nikaera.com ã®ã¢ã¯ã»ã¹è² è·ãèšæž¬ãã
setUp(
scenarios(0)
)
}
å床 ./bin/gatling.sh
ãå®è¡ããŠãå®éã«è² è·ãã¹ããè¡ã£ãŠã¿ãŸãã
âš ./bin/gatling.sh ~/D/gatling-charts-highcharts-bundle-3.5.1
GATLING_HOME is set to /Users/nika/Desktop/gatling-charts-highcharts-bundle-3.5.1
Choose a simulation number:
[0] com.nikaera.AccessSimulation
[1] computerdatabase.BasicSimulation
[2] computerdatabase.advanced.AdvancedSimulationStep01
[3] computerdatabase.advanced.AdvancedSimulationStep02
[4] computerdatabase.advanced.AdvancedSimulationStep03
[5] computerdatabase.advanced.AdvancedSimulationStep04
[6] computerdatabase.advanced.AdvancedSimulationStep05
0 # äœæãããã¹ãã·ããªãªã§ãã com.nikaera.AccessSimulation ãéžæããŠå®è¡ããŸãã
Select run description (optional)
Simulation com.nikaera.AccessSimulation started...
#...
Simulation com.nikaera.AccessSimulation completed in 10 seconds
Parsing log file(s)...
Parsing log file(s) done
Generating reports...
================================================================================
---- Global Information --------------------------------------------------------
> request count 60 (OK=60 KO=0 )
> min response time 11 (OK=11 KO=- )
> max response time 372 (OK=372 KO=- )
> mean response time 104 (OK=104 KO=- )
> std deviation 99 (OK=99 KO=- )
> response time 50th percentile 53 (OK=53 KO=- )
> response time 75th percentile 212 (OK=212 KO=- )
> response time 95th percentile 259 (OK=259 KO=- )
> response time 99th percentile 307 (OK=307 KO=- )
> mean requests/sec 5.455 (OK=5.455 KO=- )
---- Response Time Distribution ------------------------------------------------
> t < 800 ms 60 (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: /Users/nika/Desktop/gatling-charts-highcharts-bundle-3.5.1/results/accesssimulation-20210314144205502/index.html
ãã¹ãã·ããªãªã®å®è¡ã«æåããŠããããšã確èªã§ããããè€æ°ãŠãŒã¶èªèšŒããæ å ±ãå ã«è¡ããã¹ãã·ããªãªãæžããŠãããŸãã
è€æ°ãŠãŒã¶èªèšŒãè¡ããã¹ãã·ããªãªãå®è£ ãã
è€æ°ãŠãŒã¶èªèšŒãããã¹ãã·ããªãªãå®è£
ããŠãããŸããPlayFab ã§è€æ°ãŠãŒã¶ã®èªèšŒæ
å ±ãå
ã« CloudFunction ã®è² è·ãã¹ããè¡ãããšãæ³å®ããŠããŸãã1 ãã¹ãã·ããªãªãäœæããã«ãããã./user-files/simulations/
ãã©ã«ãã«æ°ãã« playfab.com
ãã©ã«ããäœæããŠããã®äžã« TestCloudFunctionSimulation.scala
ãã¡ã€ã«ãçæããŸãã
// ./user-files/simulations/playfab.com/TestCloudFunctionSimulation.scala
package com.playfab
import java.io._
import java.net.{HttpURLConnection, URL}
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
import scala.util.Random
import scala.util.parsing.json.JSON
import scala.collection.mutable.ListBuffer
import io.gatling.core.structure.PopulationBuilder
class TestCloudFunctionSimulation extends Simulation {
// PlayFab ã«ç»é²ããããŠãŒã¶ã® ID 矀
val playfabUsers = Array[String](
"user1",
"user2",
"user3",
"user4",
"user5",
"user6",
"user7",
"user8",
"user9",
"user10"
)
// PlayFab ã® TitleId åã³ Secret ãå€æ°ã«ä¿æããŠãã
val playfabId = "XXXXX"
val playfabSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
val playfabApiUrl =
s"https://${playfabId}.playfabapi.com"
ã// PlayFab ã® Login With Server Custom Id ãå©çšããŠã
// ãŠãŒã¶ã®èªèšŒæ
å ±ãååŸããããã«çšããé¢æ°
def getPlayfabAuth(serverCustomId: String): Option[Any] = {
val url = new URL(
s"${playfabApiUrl}/Server/LoginWithServerCustomId"
)
val con = url.openConnection().asInstanceOf[HttpURLConnection]
HttpURLConnection.setFollowRedirects(false)
con.setRequestMethod("POST")
con.setRequestProperty("Content-Type", "application/json")
con.setRequestProperty("X-SecretKey", playfabSecret)
con.setDoOutput(true)
val out = new OutputStreamWriter(con.getOutputStream(), "UTF-8")
out.write(s"""{
"CreateAccount": false,
"ServerCustomId": "${serverCustomId}"
}""")
out.flush()
out.close()
con.connect()
val in = con.getInputStream
val br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
val json = br.readLine()
in.close()
con.disconnect()
return JSON.parseFull(json)
}
val httpConf = http
.baseUrl(playfabApiUrl)
.header("Content-Type", "application/json")
// CloudFunction ã® Request Body ãäœæããããã«å©çšããé¢æ°
def cloudScriptDto(funcName: String, funcArgs: String): String = {
return s"""{
"FunctionName": "${funcName}",
"FunctionParameter": ${funcArgs}
}"""
}
val scenarios: ListBuffer[PopulationBuilder] =
new ListBuffer[PopulationBuilder]()
playfabUsers.foreach(userId => {
// playfabUsers ã§æå®ãããŠãŒã¶ ID æ
å ±ãå
ã«ã
// PlayFab ã®èªèšŒæ
å ±ãååŸå©çšããããšã§ã
val playfab = this.getPlayfabAuth(userId).get
val map: Map[String, Option[Any]] =
playfab.asInstanceOf[Map[String, Option[Any]]];
// æçŽã« JSON ãªããžã§ã¯ãã®ããŒã¹ãè¡ããå¿
èŠãªæ
å ±ãå€æ°ã«åãåºãã
val data = map.get("data").get.asInstanceOf[Map[String, Option[Any]]];
val entityTokenInfo =
data.get("EntityToken").get.asInstanceOf[Map[String, Option[Any]]];
val entityToken =
entityTokenInfo.get("EntityToken").get.asInstanceOf[String];
val entity =
entityTokenInfo.get("Entity").get.asInstanceOf[Map[String, Option[Any]]];
val entityId =
entity.get("Id").get.asInstanceOf[String];
// Test2 API ã«ã€ããŠã¯ CloudFunction å®è¡æã®ãã©ã¡ã¿ãã
// ã©ã³ãã æå®ããããããRandom ãçšããŠãã©ã¡ã¿ãæ£ããããã«ãã
val rand = new Random
val values = Array(
"value1",
"value2",
"value3",
"value4",
"value5"
)
val values_length = values.length
// ã¢ã¯ã»ã¹è² è·ã調æ»ããã CloudFunction API 矀ãå®è¡ããã
val pollingApiScn = scenario(s"PollingSimulation: ${entityId}")
.exec(
http("Test1 Api")
.post("/CloudScript/ExecuteFunction")
.header("X-EntityToken", entityToken)
.body(StringBody(cloudScriptDto("Test1", null)))
.check(status.is(200))
)
.exec(
http("Test2 Api")
.post("/CloudScript/ExecuteFunction")
.header("X-EntityToken", entityToken)
.body(
StringBody(
cloudScriptDto(
"Test2",
s"""{"value": "${values(rand.nextInt(values_length))}"}"""
)
)
)
.check(status.is(200))
);
// 1 ãŠãŒã¶ããã 3ç§æ¯ã« 100åã〠API 矀ãå®è¡ããéã®
// è² è·ãã¹ãã®ã·ããªãªã scenarios å€æ°ã«æ ŒçŽãã
scenarios += pollingApiScn
.inject(
atOnceUsers(100),
nothingFor(10 seconds),
atOnceUsers(100),
nothingFor(10 seconds),
atOnceUsers(100)
)
.protocols(httpConf);
});
// scenarios å€æ°ã«æ ŒçŽããããã¹ãã·ããªãªã䞊åå®è¡ãã
setUp(
scenarios(0),
scenarios(1),
scenarios(2),
scenarios(3),
scenarios(4),
scenarios(5),
scenarios(6),
scenarios(7),
scenarios(8),
scenarios(9)
)
}
ã¶ããšã€ã³ã©ã€ã³ã³ã¡ã³ãã§èª¬æãæžããŸããããéèŠãªç¹ã«ã€ããŠã®ã¿è£è¶³ããŸãã
def getPlayfabAuth
㯠PlayFab èªèšŒããããã®é¢æ°ãšãªã£ãŠããŸãããé©å®èªèšŒã«çšãããµãŒãã¹æ¯ã§é¢æ°ã®å
容ãå€æŽããããšã§ãä»ãµãŒãã¹ã§èªèšŒããããã®é¢æ°ãšããŠå©çšå¯èœã§ãã
ãŸã playfabUsers.foreach
å
ã§åãŠãŒã¶ãå®è¡ãããã¹ãã·ããªãªãçæãã€ã€ããããã scenarios
å€æ°ã«ä¿æããŠããŸããããããããšã§ãæåŸã« setUp
é¢æ°ã§ã·ããªãªããŸãšããŠã»ããã§ããããã«ãªããŸãã
playfabUsers.foreach
ã§å€ãæå®ããã®ã§ã¯ãªã CSV ã§ãã¹ãã«äžãããã£ãŒãããŒã¿ãå®çŸ©ãã æ¹æ³ããããŸããèªèšŒéšåãå«ããŠãã¹ãã·ããªãªãæžãããå Žåã«ã䟿å©ã«å©çšã§ããŸãããŸãã¢ã«ãŠã³ãæ
å ±ã CSV ãã¡ã€ã«ã«å®çŸ©ããŠãããšããã¹ããŠãŒã¶ã®æ
å ±ãæ°èŠè¿œå ãããå Žåã§ç®¡çã楜ã«ãªããŸãã
äžèšãã¹ãã·ããªãªã®ãœãŒã¹ã³ãŒããå¿çšããããšã§ãæ§ã ãªãµãŒãã¹ã§è€æ°ãŠãŒã¶èªèšŒããæ å ±ãå ã«è² è·ãã¹ããè¡ãããã®ã·ããªãªãäœæããããšãå¯èœãšãªããŸãã
ãããã«
ä»å㯠Gatling ã§è€æ°ãŠãŒã¶èªèšŒããæ å ±ãå ã«è² è·ãã¹ãããæé ã«ã€ããŠæžããŸããã
Gatling ã§çæãããã¬ããŒãã¯èŠããããæ¹åç¹ãæŽãåºããŠã³ãŒãã®æ¹åäœæ¥ãããã®ã«ãšãŠãæçšã§ããã ãŸããJMeter ãšæ¯ã¹ãŠåäœã軜ãããæ°è»œã«å®è¡ããããããã¹ãã·ããªãªãå šãŠã³ãŒãã§ç®¡çãããŠããããã·ããªãªã®æ¹å€ãçŽ æ©ãè¡ãããšãåºæ¥ãŸããã
å人çã«ã¯ãã¹ãã·ããªãªãå šãŠã³ãŒãã§èšè¿°ã§ãã Gatling ãæ°ã«å ¥ã£ãã®ã§ä»åŸãæå¹æŽ»çšããŠãããããšæããŸããããã ãGatling 以å€ã«ã Python ã§æžãã locust ã JavaScript ã§æžãã k6 ãªã©ãä»ã«ãæ°ã«ãªãããŒã«ãããã€ããã£ãã®ã§ä»åŸè©ŠããŠã¿ãããªãšèããŠããŸãã
åæã«è² è·ãã¹ã㯠JMeter äžæã ãšæã£ãŠããã®ã§ãããè² è·ãã¹ãããŒã«ã«ã¯è²ã ãããããªã®ã§ãããžã§ã¯ããèªåã«ãã£ããã®ãéžå®ããŠãããããéæãã£ããã¢ããããŠãããããšæããŸããã
åèãªã³ã¯
- Apache JMeter - Apache JMeterâ¢
- Gatling Open-Source Load Testing â For DevOps and CI/CD
- Azure é¢æ°ã䜿çšãã PlayFab CloudScript - PlayFab | Microsoft Docs
- JDK Builds from Oracle
- Maven â Welcome to Apache Maven
- sbt - The interactive build tool
- Open Source â Gatling Open-Source Load Testing
- è² è·è©ŠéšããŒã«ã»Gatlingã»CSV ãã¡ã€ã«ãš Feeder ã䜿ã£ããã¹ãã±ãŒã¹
- Locust - A modern load testing framework
- Load testing for engineering teams | k6
ã³ãŒãã®
setUp
ã§ã·ããªãªãè€æ°æå®ããç®æã«ã€ããŠã§ãããããè¯ãããæ¹ãããã°æ¯éãææããã ããŸããšå¹žãã§ã… ↩︎