การทำ Load Test ด้วย Locust
Locust คือ เครื่องมือที่ใช้ในการทำ Load test เป็น Opensource ที่พัฒนาขึ้นมาด้วย Python สามารถนำมาใช้งานได้ฟรี เราสามารถเขียน Code เพื่อกำหนดรูปแบบของ load ได้เอง และเนื่องจากการเป็น Python เราเลยสามารถ Random รูปแบบของ Requests ได้ง่ายมากๆ เป็นการจำลอง Load ที่จะเหมือนจริงมากขึ้น
ซึ่งข้อดีของเจ้าตั๊กแตนเขียว(locust แปลว่า ตั๊กแตน) คือ
- Define user behaviour in code สามารถสร้าง User Behavior ด้วย Python ได้เลย ไม่ต้องเรียนรู้การใช้งาน UI หรือ ไม่ต้องสร้าง file xml ที่กลับมาแก้ไขได้ค่อนข้างยาก
- Distributed and Scaled สามารถ run load test ได้จากหลายๆเครื่องพร้อมๆกัน(Distributed) เลยทำให้เราสามารถ simulate user เป็นหลักล้านได้
- Proven & battle tested Locust เป็น Open source ที่ถูกนำไปใช้งานในหลายๆ Application ซึ่งรูปแบบของการทำ Load test ในแต่ละ Application นั้นไม่เหมือนกัน ดังนั้นเราจึงมั้นใจได้ว่า Locust สามารถนำมาใช้ใน Application ของเราได้แน่นอน
Locust vs jMeter
เครื่องมือสำหรับการทำ Load Test ที่มีผู้ใช้งานมากที่สุดคือ jMeter แต่เนื่องจาก jMeter มีอายุมากกว่า 20 ปีมาแล้วดังนั้นจึงไม่แปลกที่ jMeter จะมีฐานผู้ใช้งานที่กว้างกว่า แต่การเติบโตของ Locust ก็เป็นสิ่งที่ต้องจับตามองเช่นกัน ดังนั้นถ้าเราลองเทียบฟังก์ชั่นการทำงานของ jMeter และ Locust จะออกมาเป็นตารางนี้
jMeter | Locust |
---|---|
พัฒนาขึ้นมาด้วย Java | พัฒนาขึ่้นมาด้วย Python |
ใช้งานผ่าน GUI เป็นหลัก | ต้องเขียน Python |
สามารถ export jmx file ออกไปใช้งานผ่าน command line | ผลลัพธ์ที่ได้เป็น python ที่สามารถ run ผ่าน command line ได้อยู่แล้ว |
สามารถ Integrate กับ Monitoring tool อย่าง PrefMon ได้ | ไม่สามารถเชื่อมต่อกับ PerfMon ได้ |
ไม่สามารถจัดการ Version ของ Test code ได้เพราะต้อง export ออกมาจาก GUI | สามารถจัดการ Version ได้เพราะเป็น Source Code |
ใช้ CPU และ Memory มากกว่า | ใช้ CPU และ Memory น้อยกว่า |
มี Script Recording | ไม่มี Script Recording(ต้องเขียน code) |
สามารถทดสอบได้หลาย Protocols | ใช้ทดสอบ Web application เป็นหลัก |
การสร้าง User Behavior
ในการทำ Load test นั้นจะแตกต่างจากการทำ Stress Test ตรงที่เราต้องการจำลองการใช้งานระบบของ User เราจึงต้องสร้าง User Behavior ให้เหมือนหรือใกล้เคียงกับการทำงานของ User มากที่สุด ดังนั้นถ้าเราทำ Load Test ให้คิดถึง Senario ที่มีคนเข้ามาใช้งาเยอะที่สุด อย่ายิง load เข้าหน้า main อย่างเดียวมันไม่ได้ประโยชน์อะไร
ขั้นตอนการทำ Load testing
-
ก่อนเริ่มต้นใช้งาน Locust เราต้องติดตั้ง locust cli ก่อน โดยเข้าไปที่ terminal(MacOS) หรือ PowerShell(windows) แล้วทำการ run command pip install หรือ pip3 install ในกรณีที่เราต้องการ run locust ผ่าน docker container ให้ลงไปดูด้านล่าง
$ pip3 install locust
หลังจากนั้นให้ตรวจสอบ ว่า locust นั้นใช้งานได้ด้วยคำสั่ง
$ locust -v
หรือถ้าเราอยากจะระบุชื่อ locust file ที่ต้องการ run (โดย default จะใช้เป็นlocustfile.py)
$ locust -f custom-locustfile.py
และถา้อยากระบุ host เข้าไปทาง command line เลยก็ทำได้โดยที่ทำการใส่ option เข้าไปแบบนี้(ไม่ต้องใส่ / ต่อท้าย)
$ locust - -host=<hostname>
-
ขั้นตอนต่อไปเราก็จะเริ่มเขียน Code โดยที่เริ่มจากการสร้างไฟล์ locustfile.py ไว้ใน project ของเรา ไฟล์นี้คุณตั้งชื่อตาม User Behavior ได้เลย หรือถ้าไฟล์ที่ใช้ในการทดสอบมีเยอะมากก็ตั้ง folder load-test ขึ้นมาเก็บ load test file ต่างๆเอาไว้ จะได้จัดการได้ง่ายขึ้น
-
import locust เข้ามาใช่งานก่อน
from locust import HttpUser, task
-
เขียน Code เพื่อสร้าง User Behavior ซึ่ง Locustfile จะทำงานได้ก็ต่อเมื่อมีอย่างน้อย 1 Class ที่ inherit มาจาก HttpUser
class HelloWorldUser(HttpUser): @task def hello_world(self): self.client.get('/')
-
ทำ Load test ด้วยคำสั่ง
$ locust
หลังจากนั้นจะได้ Web application ของ Locust หน้าตาแบบนี้
ถ้า Browser ของคุณไม่ได้เด้งขึ้นมาโดยอัตโนมัติให้เข้าไปที่ http://localhost:8090
-
ระบุจำนวนของ Users และ URL ของ Web Application หรือ Web API ที่เราต้องการทำ Load test
- Number of users ใส่จำนวนของ users ที่เข้าไปพร้อมกันมากที่สุด(Peak concurrent users)
- Spawn rate จำนวน users ที่ start task ขึ้นมาทำงานภายใน 1 วินาที
- Host Base URL ของ target(path เราจะใส่ไว้ใน Task)
-
หลังจากกด Start Swaming Lucust ก็จะพาเข้าไปสู่หน้า report ของการทำ Load test
Option ต่างๆที่สามารถใส่เพิ่มเติมได้
Waittime Attribute
เราสามารถ delay request ในแต่ละ task ได้ด้วยการกำหนด waittime attribute เข้าไปใน class แบบนี้
|
|
ในตัวอย่างนี้จะเป็นการ delay request ในแต่ละ task ออกไป 1-5 วินาที
กำหนด Event on_start
เราสามารถระบุสิ่งที่ต้องทำก่อนการ run load test เช่น login ด้วยการใส่ on_start เข้าไปใน class แบบนี้
|
|
กำหนด Weight ให้กับแต่ละ task ได้
โดยปกติ locust จะกระจาย load ให้กับทุกๆ task เท่าๆกัน ถ้าเราอยากให้หน้าไหนหรือ task ไหมมีการใช้งานมากกว่าคนอื่นสามารถกำหนด Weight เข้าไปได้แบบนี้
|
|
ในตัวอย่างนี้ locust จะทำการส่ง request เข้าไปที่หน้า index มากกว่า หน้า about 3 เท่าโดยประมาณเพราะเรากำหนด weight เป็นอัตรส่วน 3:1
การใช้งาน locust ผ่านทาง docker
แน่นอนว่าการทำ load test ในปัจจุบันเราต้องการทำ Automation ดังนั้นเราจึงหลีกเลี่ยงการใช้ Locust ผ่านทาง docker ไม่ได้ ซึ่งขั้นตอนการ run locust ผ่านทาง docker มีดังนี้
- เราต้องสร้าง locustfile.py ขึ้นมาก่อน
- run docker command เพื่อสร้าง locust container ซึ่งเราต้อง run command นี้ใน path ที่มี locustfile.py
เราใช้ parameters
$ docker run -p 8089:8089 \ -v $PWD:/mnt/locust locustio/locust \ -f /mnt/locust/locustfile.py
- -p เพื่อ bind port 8090 ออกมาข้างนอกเพราะ locust จะ run web application ขึ้นมาที่ port ouh
- -v ทำ bind mount เพื่อนำทุกไฟล์ที่ีอยู่ใน folder ปัจจุบันเข้าไปไว้ใน container ของ locust โดยจะไปเก็บไว้ใน /mnt/locust(path นี้เป็น path ภายใน container)
- ส่วน -f จะเป็น parameter ของ locust เพราะวางอยู่หลังชื่อ image(locustio/locust) โดยที่ -f จะระบุชื่อ locustfile ซึ่งในกรณีนี้เราต้องการอ้างถึง path ที่เราได้ทำ bind mount เข้ามาใน container(/mnt/locust) เราจึงต้องใส่ -f /mnt/locust/locustfile.py
- Locust จะสร้าง web application ขึ้นมาที่ http://localhost:8090
- กดคลิก New Test ที่มุมขวาบน
- ระบุจำนวนของ Users และ URL ของ Web Application หรือ Web API ที่เราต้องการทำ Load test
- Number of users ใส่จำนวนของ users ที่เข้าไปพร้อมกันมากที่สุด(Peak concurrent users)
- Spawn rate จำนวน users ที่ start task ขึ้นมาทำงานภายใน 1 วินาที
- Host Base URL ของ target(path เราจะใส่ไว้ใน Task)
- หลังจากนั้นกดปุ่ม Start swarming แล้วเข้าไปดูผลลัพธ์ของการทำ load test ได้่เลย
การใช้งาน locust ด้วย Docker Compose
อีกหนึ่งทางเลือกของการ run locust container คือ docker-compose ซึ่งมีขั้นตอนดังนี้
-
เราจะต้องสร้าง docker-compose.yml ขึ้นมาก่อน
-
ใส่เนื้อหานี้ลงไปใน docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
version: '3' services: master: image: locustio/locust ports: - "8089:8089" volumes: - ./:/mnt/locust command: -f /mnt/locust/locustfile.py --master -H http://master:8089 worker: image: locustio/locust volumes: - ./:/mnt/locust command: -f /mnt/locust/locustfile.py --worker --master-host master
เราสามารถ run locust ขึ้นมาได้ด้วยคำสั่ง
$ docker-compose up -d
แต่เนื่องจากในตัวอย่างนี้เรามีการนิยาม master และ worker เราจึงสามารถ scale ตัว worker ได้ด้วยคำสั่ง
$ docker-compose up --scale worker=4
นอกจากการทำ Distributed load test ด้วย docker compose แล้วเรายังสามารถ deploy locust ลงไปใน Kubernetes cluster เพื่อทำ Distributed load test ได้อีกด้วยลองอ่านต่อที่บทความ การทำ Distributed load test บน Kubernetes cluster