ããã¯ããªã«ãããããŠæžãããã®ïŒ
- Locustãšããè² è·ãã¹ãããŒã«ããããšèãããã¹ãã·ããªãªãããã°ã©ã ã§æžãããããªã®ã§è©ŠããŠã¿ããããš
Locust - A modern load testing framework
ä»åã¯ãã©ããªããŒã«ãææ¡ãããšãããç®æšã«è©ŠããŠã¿ãŸãã
LocustïŒ
Pythonã§æžããããè² è·ãã¹ãããŒã«ã§ãã
Locust - A modern load testing framework
GitHubäžã®staræ°ãå€ããŠãå²ãšäººæ°ã®ããŒã«ã®ããã«èŠããŸãã
GitHub - locustio/locust: Scalable user load testing tool written in Python
ãªãã£ã·ã£ã«ãµã€ããGitHubã«ãããšã以äžã®ãããªç¹åŸŽãæã€ããã§ãã
â»GitHubã®å
容ã®æ¹ã现ããã§ãã
- ãã¹ãã·ããªãªãPythonã³ãŒãã§æžãããšãå¯èœ
- ã¹ã±ãŒã©ãã«ã§ãåæ£å®è¡ãå¯èœ
- Web UIä»ã
- ã©ã®ãããªã·ã¹ãã ã§ããã¹ããã§ããïŒãã ããLocustã®ã³ã¢æ©èœã¯Webãã¿ãŒã²ããã«ããŠããïŒ
- å°ããäœãããŠããã®ã§ãããã¯ã容æ
Locustã¯ãIOã«é¢ããéšåã«geventãšããã©ã€ãã©ãªã䜿çšããŠããŸãã
What is gevent? — gevent 1.4.1.dev0 documentation
ã¡ãªã¿ã«ãLocustã¯ãã€ããŽããæå³ãããã§ãããããŽãèŠããšã確ãã«âŠã
æ©èœçã«ã¯ãããããèŠãŠãããšApache JMeterãªã©ã®æ¹ãå€æ©èœã«èŠããããããã®ã§ãããæ段ã®ã²ãšã€ãšããŠã¡ãã£ãš
æŒãããŠã¿ããšããŸãããã
Locustã®ã€ã³ã¹ããŒã«
ã§ã¯ããŸãæåã«Locustãã€ã³ã¹ããŒã«ããŸãã
Installation — Locust 0.9.0 documentation
Locustã§ãµããŒããããŠããPythonã®ããŒãžã§ã³ã¯ããã¡ãã
Installation / Supported Python Versions
ä»åã¯ãUbuntu Linux 18.04 LTSäžã§ãPython 3.6ã§äœ¿ã£ãŠã¿ãŸãã
pipã§ã€ã³ã¹ããŒã«ãããããã®ã§ãããŒãžã§ã³ç¢ºèªã
$ python3 -V Python 3.6.7 $ pip3 -V pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)
ã€ã³ã¹ããŒã«ã
$ python3 -m pip install locustio
ã·ã§ã«ãèµ·åããªãããšãlocustãåãããããã«ãªã£ãŠããŸãã
$ locust --version [2019-01-03 04:30:31,327] bdbddbe84a18/INFO/stdout: Locust 0.9.0 [2019-01-03 04:30:31,327] bdbddbe84a18/INFO/stdout:
ããšã¯ãMax open fiilesã«ã¯æ³šæããŠãããæ¹ãããã§ããããšã
Installation / Increasing Maximum Number of Open Files Limit
ããã§ãæºåã¯å®äºã§ãã
ä»åã®ãã¹ãã¿ãŒã²ãã
ããŠãLocustã䜿ã£ããã¹ãã·ããªãªãæžããããšããã§ããããã¹ã察象ããªããšã©ãã«ããªããŸããã
ãã°ã€ã³ãšããã£ãæ¹ããããâŠã§ããäœãã®é¢åã ãâŠãšæ©ãã çµæãRedmineã䜿ãããšã«ããŸããã
Docker Composeã§ããã£ãããšçšæã
docker-compose.yml
version: '3' services: redmine: image: redmine:4.0.0 ports: - "3000:3000" restart: always environment: REDMINE_DB_MYSQL: "mysql" REDMINE_DB_DATABASE: "redmine" REDMINE_DB_USERNAME: "user" REDMINE_DB_PASSWORD: "password" mysql: image: mysql:5.7.24 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: "secret" MYSQL_DATABASE: "redmine" MYSQL_USER: "user" MYSQL_PASSWORD: "password"
èµ·åã
$ docker-compose up
ãã¹ã察象ã®ãŠãŒã¶ãŒã¯ãããã©ã«ãã®ãadminãããã®ãŸãŸäœ¿ãããšã«ããŸãããã¹ã¯ãŒãã¯ããadmin-passwordãã«
å€æŽããŸããã
ãã®Redmineãžã¯ããhttp://192.168.0.3:3000ãã§ã¢ã¯ã»ã¹ãããã®ãšããŸãã
Locustã§ãã¹ããæžã
ã§ã¯ããããããã¹ããæžããŠã¿ããšããŸãããã
ãã®ããããèŠãªããâŠ
Quick start — Locust 0.9.0 documentation
Writing a locustfile — Locust 0.9.0 documentation
https://github.com/locustio/locust/tree/master/examples
ãŸãã¯æžããŠã¿ãã®ãããã¡ãã
locustfile.py
from locust import HttpLocust, TaskSet, task import re class UserBehavior(TaskSet): def on_start(self): self.login() def on_stop(self): self.logout() def login(self): response = self.client.get("/login") csrf_param = re.search("<meta name=\"csrf-param\" content=\"([^\"]+)\" />", response.text).group(1) csrf_token = re.search("<meta name=\"csrf-token\" content=\"([^\"]+)\" />", response.text).group(1) self.client.post("/login", {"username": "admin", "password": "admin-password", csrf_param: csrf_token}) def logout(self): response = self.client.get("/") csrf_param = re.search("<meta name=\"csrf-param\" content=\"([^\"]+)\" />", response.text).group(1) csrf_token = re.search("<meta name=\"csrf-token\" content=\"([^\"]+)\" />", response.text).group(1) self.client.post("/logout", {csrf_param: csrf_token}) @task def top(self): self.client.get("/") @task(2) def mypage(self): with self.client.get("/my/page", catch_response = True) as response: if response.status_code != 200: response.failure("not authenticated???") @task def projects(self): self.client.get("/projects") class RedmineUser(HttpLocust): task_set = UserBehavior min_wait = 500 max_wait = 1000
æåã«ãHttpLocustïŒLocustã®ãµãã¯ã©ã¹ïŒãç¶æ¿ããã¯ã©ã¹ãäœæããŸãã
class RedmineUser(HttpLocust): task_set = UserBehavior min_wait = 500 max_wait = 1000
task_setã«ã¯ãå®éã«ãã¹ããèšèŒããã¯ã©ã¹ãæž¡ããŸãã
min_waitãšmax_waitã¯ãã¿ã¹ã¯ïŒåŸè¿°ïŒã®éã®åŸ
æ©æéã®æå°ãæ倧ãããããæå®ããŸãïŒããªç§ïŒããã®éã®æéã§ãã¿ã¹ã¯éã§
ã©ã³ãã ã«waitããŸãã
wait_functionã«é¢æ°ãæå®ããããšã§ããã£ãšçŽ°ããã³ã³ãããŒã«ããããšãå¯èœãªããã§ãã
ç¶ããŠããã¹ãã®å 容ãå®çŸ©ããã®ãããã¡ãã®TaskSetãç¶æ¿ããã¯ã©ã¹ã
class UserBehavior(TaskSet):
ä»åã¯ããŠãŒã¶ãŒã®ã·ããªãªã®éå§ãçµäºæã«ãããããã°ã€ã³ããã°ã¢ãŠãããããã«äœæããŸããã
â»ãã°ã€ã³ããã°ã¢ãŠãã«ã¯CSRF察çãžã®å¯Ÿå¿ãå
¥ããŠãããŸããâŠ
def on_start(self): self.login() def on_stop(self): self.logout() def login(self): response = self.client.get("/login") csrf_param = re.search("<meta name=\"csrf-param\" content=\"([^\"]+)\" />", response.text).group(1) csrf_token = re.search("<meta name=\"csrf-token\" content=\"([^\"]+)\" />", response.text).group(1) self.client.post("/login", {"username": "admin", "password": "admin-password", csrf_param: csrf_token}) def logout(self): response = self.client.get("/") csrf_param = re.search("<meta name=\"csrf-param\" content=\"([^\"]+)\" />", response.text).group(1) csrf_token = re.search("<meta name=\"csrf-token\" content=\"([^\"]+)\" />", response.text).group(1) self.client.post("/logout", {csrf_param: csrf_token})
å®è¡ãããšããããŸããããã®æžãæ¹ã ãšãŠãŒã¶ãŒãããã1åãããã°ã€ã³ããã°ã¢ãŠããè¡ããŸããã
ããšã¯ãã¿ã¹ã¯ã®å®çŸ©ã§ãã@taskãã³ã¬ãŒã¿ãŒã§ã¿ã¹ã¯ãå®çŸ©ããŸãã
@task def top(self): self.client.get("/") @task(2) def mypage(self): with self.client.get("/my/page", catch_response = True) as response: if response.status_code != 200: response.failure("not authenticated???") @task def projects(self): self.client.get("/projects")
@taskãã³ã¬ãŒã¿ãŒã®åŒæ°ã«ã¯weightãæå®ã§ããã¿ã¹ã¯å®è¡ã®å²åã調æŽã§ããŸããçç¥ããæã®weightã¯1ãªã®ã§ãä»åã®äŸã§ã¯
mypageã¿ã¹ã¯ã¯topããã³projectsã«æ¯ã¹ããš2åå®è¡ãããããšã«ãªããŸãã
ããšãç¹ã«èª¬æãªã䜿ã£ãŠããŸããããself.clientãšæžããŠããã®ã¯Locustã®HTTPã¯ã©ã€ã¢ã³ãã§ããå®äœã¯HttpSessionãšãã
ã¯ã©ã¹ã§ãHTTPã®GETãPOSTãPUTãªã©ã«å¯Ÿå¿ããã¡ãœãããå®è¡ã§ããŸãã
@task def top(self): self.client.get("/")
ãŸããcatch_responseã«Trueãèšå®ãããšãéåžžã¯Responseãšããã¯ã©ã¹ãè¿ããšããããResponseContextManagerã
è¿ãããã«ãªããsuccessïŒfailureãšãã£ãããã¹ãã®æåã倱æãå¶åŸ¡ããããšãã§ããããã«ãªããŸãã
@task(2) def mypage(self): with self.client.get("/my/page", catch_response = True) as response: if response.status_code != 200: response.failure("not authenticated???")
ä»åã¯ããã€ããŒãžãžã®ã¢ã¯ã»ã¹ã¯ãæªãã°ã€ã³ç¶æ
ã ãšãã°ã€ã³ããŒãžãžãªãã€ã¬ã¯ãããããšããã®ã§ããã°ã€ã³
ã§ããŠããããšã確èªããããã«ãã²ãšæéå ããŸããã
å®è¡ããŠã¿ã
ãããŸã§ã§ãããšããã§ãå®è¡ããŠã¿ãŸãããã
äœæããlocustfile.pyããããã£ã¬ã¯ããªã§ã以äžã®ã³ãã³ããå®è¡ããŸãã
$ locust --host=http://192.168.0.3:3000 [2019-01-11 12:34:02,388] be01ed106c53/INFO/locust.main: Starting web monitor at *:8089 [2019-01-11 12:34:02,388] be01ed106c53/INFO/locust.main: Starting Locust 0.9.0
ã--hostãã®æå³ã¯ããã¹ã察象ã®ãã¹ããæããŸããäŸã®ããã«ããhttp://ããã®åœ¢åŒã§æå®ããŸãã
ãã¹ããæžããããã¡ã€ã«ã®ååã¯ããã©ã«ãã§ãlocustfile.pyããšãªããååãç°ãªãå Žåã¯ã-fãã§æå®ããããã§ãã
ã³ã³ãœãŒã«ã«ãåºãŠããŸããã8089ããŒãã§Web UIããªãã¹ã³ããŠããŸãã®ã§ããhttp://[LocustãåããŠãããµãŒããŒ]:8089ãã«
ã¢ã¯ã»ã¹ããŠã¿ãŸãã
ãããšãå³ã®ããã«Web UIãçŸãããNumber of users to simulateïŒãŠãŒã¶ãŒæ°ïŒããšãHatch rateïŒç§ãããäœãŠãŒã¶ãŒå¢ãããŠãããïŒãã
æ±ããããã®ã§ããã¡ããå
¥åããŠãStart swarmingããæŒããšããã¹ããå§ãŸããŸãã
ä»åã¯ãNumber of users to simulateãã20ããHatch rateãã2ã«ããŠãã¹ãéå§ã
ãã¹ãå®è¡äžãçµæããªã¢ã«ã¿ã€ã ã§æŽæ°ãããŠãããŸãã
ãã¹ããçµäºãããã«ã¯ãå³äžã«ãããSTOPããæŒããŸãã
STATUSããSTOPPEDãã«ãªãããã®äžã«ãããNew testããªã³ã¯ãæŒããšããŸãæ°ãããã¹ããå§ããããšãã§ããŸãã
â»ãNumber of users to simulateããšãHatch rateãã®å
¥åãæ±ããããŸã
çµæã®èªã¿æ¹ã¯ãããçšåºŠãŸããŸã§ããã
- requests ⊠ãªã¯ãšã¹ãããåæ°
- fails ⊠倱æãããªã¯ãšã¹ãã®åæ°
- Median (ms) ⊠äžå€®å€
- Average (ms) ⊠平åå€
- Min (ms) / Max (ms) ⊠æå°ãæ倧
- Content Size (byte) ⊠ã³ã³ãã³ãã®ãµã€ãº
- reqs/sec ⊠ç§ãããã«å®è¡ãããªã¯ãšã¹ãæ°
åé ç®ã®å称ãã¯ãªãã¯ããããšã§ããœãŒãããããšãã§ããããããŸãã
æåŸã®è¡ã«ã¯ãTotalããããããã¡ãã®ãreqs/secããšããŒãžã®å³äžéšã«ãããRPSãã®å€ãäžèŽããŸãã
ãŸãããããŸã§èŠãŠããã®ã¯ãStaticsããªã®ã§ãããé£ã®ãChartããæŒããšã°ã©ããèŠããã
ãFailuresããæŒããšããªã¯ãšã¹ãã«å€±æããå Žåã«ããã®çç±ãèŠãããããŸãã
èªåã¯ããã°ã€ã³ã«æåãã£ãšå€±æããŠããŠãããã«ãã£ãšãšã©ãŒãåºãŠããŸããâŠã
ããšãäŸå€ã®æ å ±ãèŠãããçµæã®ããŠã³ããŒããã§ããããããŸãã
次ã®ãã¹ããå®è¡ããããLocustãçµäºãããšãçµæã¯ãªããªã£ãŠããŸãã®ã§ååããŠãããŸãããã
ãªããLocustçµäºæã«ããè¿ãæ å ±ãåŸãããšãã§ããŸãã
[2019-01-11 13:00:20,978] be01ed106c53/INFO/locust.main: Running teardowns... Name # reqs # fails Avg Min Max | Median req/s -------------------------------------------------------------------------------------------------------------------------------------------- GET / 532 0(0.00%) 112 21 568 | 97 5.40 GET /login 20 0(0.00%) 47 18 154 | 27 0.00 POST /login 20 0(0.00%) 365 247 542 | 320 0.00 POST /logout 20 0(0.00%) 838 623 1012 | 840 0.00 GET /my/page 1152 0(0.00%) 162 28 602 | 140 12.40 GET /projects 518 0(0.00%) 116 25 342 | 110 4.50 -------------------------------------------------------------------------------------------------------------------------------------------- Total 2262 0(0.00%) 22.30 Percentage of the requests completed within given times Name # reqs 50% 66% 75% 80% 90% 95% 98% 99% 100% -------------------------------------------------------------------------------------------------------------------------------------------- GET / 532 97 130 150 160 200 250 340 430 570 GET /login 20 28 57 79 85 96 150 150 150 150 POST /login 20 360 380 480 490 540 540 540 540 540 POST /logout 20 840 880 880 960 1000 1000 1000 1000 1000 GET /my/page 1152 140 180 210 240 300 350 410 440 600 GET /projects 518 110 140 150 170 200 240 270 280 340 -------------------------------------------------------------------------------------------------------------------------------------------- Total 2262 120 160 180 200 270 330 430 570 1000
ãã¹ãã·ããªãªã®èª¬æã®æã«ãæžããŸããããon_startããã³on_stopã§å®è¡ããããã«æå®ããããã°ã€ã³ããã³ãã°ã¢ãŠãã¯
20åïŒïŒãŠãŒã¶ãŒæ°ïŒããå®è¡ãããŠããŸããã
ãã®ãããã¯ãã¿ã¹ã¯ãå®çŸ©ããã¯ã©ã¹ã®ã©ã€ããµã€ã¯ã«ã®é¢ä¿ã§ãããããã
Web UIãªãã§å®è¡ãã
ããæžããšãUIããå®è¡ããŠåæ¢ãããªããŠã¯ãããªãâŠïŒãšæããããããŸããããã--no-webããªãã·ã§ã³ã䜿ãããšã§ã
Web UIãªãã§ãå®è¡ããããšãã§ããŸãã
Running Locust without the web UI — Locust 0.9.0 documentation
ãã®å Žåãã-cãã§ãNumber of users to simulateããã-rãã§ãHatch rateããæå®ããå¿ èŠããããŸãã
$ locust --host=http://192.168.0.3:3000 --no-web -c 20 -r 2 -t 180s
ãŸããå®è¡æéã決ããå Žåã¯ãã-tãã§æå®ããããšãã§ããŸãã
â»æå®ããªããšã延ã
ãšå®è¡ãç¶ããã®ã§ãCtrl-cã§æ¢ããŸããã
ãlocust -hãã§ããã«ããèŠãŠã¿ãŸãããã
çµæããã¡ã€ã«ãšããŠæ¬²ããå Žåã¯ãã--csvãã§çµæãåºåããŸãã
Retrieve test statistics in CSV format — Locust 0.9.0 documentation
$ locust --host=http://192.168.0.3:3000 --no-web -c 20 -r 2 -t 180s --csv perf-test
ã--csvãã§äžããå€ãprefixã«ããŠãrequests.csvãšdistribution.csvã®2ã€ã®ãã¡ã€ã«ãã§ãããããŸãã
ããã¯ãWeb UIããããŠã³ããŒãã§ãããã®ãšåãã§ãã
perf-test_requests.csv
"Method","Name","# requests","# failures","Median response time","Average response time","Min response time","Max response time","Average Content Size","Requests/s" "GET","/",1011,0,99,110,22,631,4618,5.60 "GET","/login",20,0,26,39,15,100,4805,0.11 "POST","/login",20,0,320,343,238,505,16570,0.11 "POST","/logout",20,0,730,750,572,950,4377,0.11 "GET","/my/page",1967,0,140,158,27,598,10468,10.90 "GET","/projects",1012,0,98,108,25,560,5665,5.61 "None","Total",4050,0,120,137,15,950,7780,22.43
perf-test_distribution.csv
"Name","# requests","50%","66%","75%","80%","90%","95%","98%","99%","100%" "GET /",1011,99,120,140,150,190,230,310,460,630 "GET /login",20,26,49,59,74,83,100,100,100,100 "POST /login",20,330,370,400,420,490,510,510,510,510 "POST /logout",20,750,790,890,890,930,950,950,950,950 "GET /my/page",1967,140,170,210,230,290,340,390,440,600 "GET /projects",1012,98,120,140,150,190,220,250,290,560 "Total",4050,120,150,170,190,250,310,390,490,950
ãã£ãšã·ããªãªã£ãœããã®ãæžããŠã¿ã
å ã»ã©äœæããã·ããªãªã¯ãã¿ã¹ã¯ã®éã¿ä»ãã ã決ãããã®ã®ãç¹ã«å®è¡é ã¯æå®ããŠããŸããã§ããã
ãã®ããããã¡ãããšå®çŸ©ããå Žåã¯ãTaskSequenceãš@seq_taskãã³ã¬ãŒã¿ãŒã䜿ããŸãã
seq-senario-locustfile.py
from locust import HttpLocust, TaskSequence, seq_task import re class UserBehavior(TaskSequence): @seq_task(1) def login(self): response = self.client.get("/login") csrf_param = re.search("<meta name=\"csrf-param\" content=\"([^\"]+)\" />", response.text).group(1) csrf_token = re.search("<meta name=\"csrf-token\" content=\"([^\"]+)\" />", response.text).group(1) self.client.post("/login", {"username": "admin", "password": "admin-password", csrf_param: csrf_token}) @seq_task(99) def logout(self): response = self.client.get("/") csrf_param = re.search("<meta name=\"csrf-param\" content=\"([^\"]+)\" />", response.text).group(1) csrf_token = re.search("<meta name=\"csrf-token\" content=\"([^\"]+)\" />", response.text).group(1) self.client.post("/logout", {csrf_param: csrf_token}) @seq_task(2) def top(self): self.client.get("/") @seq_task(3) def mypage(self): with self.client.get("/my/page", catch_response = True) as response: if response.status_code != 200: response.failure("not authenticated???") @seq_task(4) def projects(self): self.client.get("/projects") class RedmineUser(HttpLocust): task_set = UserBehavior min_wait = 500 max_wait = 1000
ã·ããªãªãå®çŸ©ããã¯ã©ã¹ã®ç¶æ¿å ãTaskSequenceãšãªãã
class UserBehavior(TaskSequence):
ã¿ã¹ã¯ã®å®è¡é ã¯@seq_taskã§æå®ããŸãã
@seq_task(2) def top(self): self.client.get("/") @seq_task(3) def mypage(self): with self.client.get("/my/page", catch_response = True) as response: if response.status_code != 200: response.failure("not authenticated???") @seq_task(4) def projects(self): self.client.get("/projects")
ä»åã¯ããã°ã€ã³ããã°ã¢ãŠããã¿ã¹ã¯ã«çµã¿èŸŒã¿ãŸããã
確èªãçãã«ã30ç§éå®è¡ã
$ locust --host=http://192.168.0.3:3000 -f seq-senario-locustfile.py --no-web -c 20 -r 2 -t 30s
ä»åã¯ããã°ã€ã³ããã°ã¢ãŠãã¯ãŠãŒã¶ãŒã®æ°ã ãå®è¡ãã§ã¯ãããŸãããã
[2019-01-11 13:17:27,596] be01ed106c53/INFO/locust.main: Running teardowns... Name # reqs # fails Avg Min Max | Median req/s -------------------------------------------------------------------------------------------------------------------------------------------- GET / 191 0(0.00%) 143 24 420 | 130 7.80 GET /login 107 0(0.00%) 57 15 207 | 40 3.80 POST /login 105 0(0.00%) 467 226 806 | 460 3.80 POST /logout 90 0(0.00%) 274 85 561 | 260 3.70 GET /my/page 96 0(0.00%) 220 34 509 | 190 3.80 GET /projects 94 0(0.00%) 152 28 388 | 150 3.80 -------------------------------------------------------------------------------------------------------------------------------------------- Total 683 0(0.00%) 26.70 Percentage of the requests completed within given times Name # reqs 50% 66% 75% 80% 90% 95% 98% 99% 100% -------------------------------------------------------------------------------------------------------------------------------------------- GET / 191 130 160 190 200 230 270 310 380 420 GET /login 107 40 56 80 86 120 140 180 190 210 POST /login 105 460 500 560 580 630 680 750 770 810 POST /logout 90 270 330 360 390 440 510 560 560 560 GET /my/page 96 190 250 300 320 390 440 480 510 510 GET /projects 94 150 170 170 190 240 280 360 390 390 -------------------------------------------------------------------------------------------------------------------------------------------- Total 683 160 230 290 350 450 530 620 670 810
åæ£å®è¡ããŠã¿ãã
æåŸã«ãåæ£å®è¡ããŠã¿ãŸãã
Running Locust distributed — Locust 0.9.0 documentation
Locustãå®è¡ããããŒãã¯ããšããããåãããŠã¿ããšããããšã§ãDockerã§3ã€çšæã172.17.0.2ã4ãšããŸãã
ã·ããªãªã¯ãå ã»ã©ã®ã¿ã¹ã¯ã®å®è¡é ãæå®ãããã®ã䜿ã£ãŠå®è¡ã
åæ£å®è¡æã«ã¯ãmasterïŒã²ãšã€ïŒãšslaveãšãªãããŒãïŒ2ã€ïŒãéžã³ãŸããWeb UIã¯ãmasterã§ã®ã¿åããŸãã
masterã§ã¯ãã--masterããæå®ããŠå®è¡ãmasterã¯ã172.17.0.2ã®ãã®ã䜿ããŸãã
$ locust --host=http://192.168.0.3:3000 -f seq-senario-locustfile.py --master
slaveã§ã¯ã以äžã®ã³ãã³ããå®è¡ã2ã€ã®ããŒããšããå®è¡ããŸãã
$ locust --host=http://192.168.0.3:3000 -f seq-senario-locustfile.py --slave --master-host 172.17.0.2
ã€ãŸããslaveã«ãã·ããªãªã¯é ã£ãŠããå¿ èŠããããŸãããšã
ãã®ç¶æ ã§masterã®Web UIãèŠããšãå³äžã«ãSLAVESãã®è¡šç€ºãè¿œå ãããŠããŸãã
ã§ãå®è¡ãæäœæ¹æ³èªäœã¯ãéåžžãšåãã§ãã
ä»åã¯ããNumber of users to simulateãã20ã«ããHatch rateãã«2ãæå®ããŸããã
ãããŠãslaveã²ãšã€ãããã以äžã®ãããªãã°ãåºåãããŸãã
[2019-01-11 13:28:23,783] dce69b8cc910/INFO/locust.runners: Hatching and swarming 10 clients at the rate 1 clients/s... [2019-01-11 13:28:33,793] dce69b8cc910/INFO/locust.runners: All locusts hatched: RedmineUser: 10
ãŠãŒã¶ãŒã®ååãå²ãåœãã£ãŠããŸããã
ãšããããšã¯ããã¹ãå®è¡æã«æå®ãããŠãŒã¶ãŒã¯slaveã«åé
ãããŠå®è¡ãããïŒmasterã¯è² è·ããããäœæ¥ã¯ããªãïŒãšãã
ããšã§ããã
Web UIã«ããSlavesãã¿ããå¢ããŠããŠãèªèããŠããslaveã®ç¢ºèªãšããã¹ãã®å®è¡äžã§ããã°äœãŠãŒã¶ãŒãããããã®
slaveã«å²ãåœãŠãããŠãããã確èªããããšãã§ããŸãã
ã¡ãªã¿ã«ãslaveã¯masterãåæ¢ãããšèªåçã«åæ¢ããŸãã
æåŸã«ããã®åæ£å®è¡ãWeb UIãªãã§è¡ã£ãŠã¿ãŸãããã
ãã®å Žåãå ã«slaveãå¿ èŠãªæ°ã ãèµ·åããŠãããŸãã
$ locust --host=http://192.168.0.3:3000 -f seq-senario-locustfile.py --slave --master-host 172.17.0.2
ãã®åŸãmasterãèµ·åããŸããã--masterããä»ãã以å€ã¯ãã¹ã¿ã³ãã¢ãã³ã§Web UIãªãã§å®è¡ããŠããå Žåãšåãã§ãã
$ locust --host=http://192.168.0.3:3000 -f seq-senario-locustfile.py --master --no-web -c 20 -r 2 -t 30s --csv perf-test-dist
ãã®é çªãéã«ãããšãmasterã¯slaveãããªãéã¯åŸ
æ©ç¶æ
ã«ãªããŸãããã²ãšã€ã§ãslaveãèªèãããšããã«ãã¹ãã
å§ããŠããŸããŸãâŠã
ãŸãšã
Pythonã§æžãããè² è·ãã¹ãããŒã«ãLocustã䜿ã£ãŠã¿ãŸããã
Pythonã§ç°¡åã«ã·ããªãªãæžããããããããUIããããåæ£å®è¡ãå¯èœãšãããã䟿å©ã§ãã
ãã®åé¢ãApache JMeterã»ã©ã®æ©èœã¯ãªãããã ã£ããïŒã¬ã³ãŒããŒãšããâŠïŒããŸãã
ãã©ã¡ãŒã¿ãŒãšããã°ã€ã³ã§äœ¿ããŠãŒã¶ãŒããCSVãšãã«ã§ããªãã®ïŒãšããã®ã調ã¹ãŠã¿ãã®ã§ãããèªåã§æžããïŒ
ãšããæãã¿ããã§ããã
How to Run Locust with Different Users | BlazeMeter
ãŸããã³ã³ã»ããçã«ã¯ããã§ãããããããšã
ã«ã¹ã¿ã ã¯ã©ã€ã¢ã³ãã®äœãæ¹ãã
Testing other systems using custom clients — Locust 0.9.0 documentation
æŠããåºæ¬çãªç¯å²ã§æ°ã«ãªããšããã¯ãã£ãšè§Šããã®ã§ã¯ãªãã§ããããã䜿ãããšããã§ã¯ã掻çšããŠããããã§ããã