ćććÆććŖć«ććććć¦ęøćććć®ļ¼
- 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
ę¦ććåŗę¬ēćŖēÆå²ć§ę°ć«ćŖććØćććÆćć£ćØ触ććć®ć§ćÆćŖćć§ćććććä½æćććØććć§ćÆćę“»ēØćć¦ććććć§ććć