คุณได้เปิดใช้งาน Endpoint มันส่งคืน JSON ที่ถูกต้องใน Postman แต่คุณไม่รู้ว่าจะเกิดอะไรขึ้นเมื่อมีไคลเอนต์ 200 รายเข้ามาพร้อมกัน มันสามารถรองรับคำขอ 500 รายการต่อวินาทีได้หรือไม่ หรือความหน่วงจะพังทลายลงที่ 50? ApacheBench สามารถตอบคำถามนั้นได้ด้วยคำสั่งเดียว
ApacheBench หรือที่เรียกสั้นๆ ว่า ab เป็นเครื่องมือบรรทัดคำสั่งที่ส่งคำขอ HTTP จำนวนคงที่ไปยัง URL เดียว และรายงานปริมาณงาน (throughput) และความหน่วง (latency) มันมาพร้อมกับ Apache HTTP Server และมีมานานหลายทศวรรษแล้ว มันมีขนาดเล็ก ทำงานได้รวดเร็ว และช่วยให้คุณทราบได้อย่างรวดเร็วว่า endpoint หนึ่งสามารถรองรับโหลดได้มากแค่ไหน
คู่มือนี้ครอบคลุมการติดตั้ง ab การเรียกใช้การทดสอบพื้นฐาน การทดสอบ POST endpoints การอ่านผลลัพธ์ และการทราบว่า ab ไม่ใช่เครื่องมือที่เหมาะสมอีกต่อไปเมื่อใด ทุกคำสั่งในที่นี้จะสอดคล้องกับแฟล็กที่ระบุไว้ใน เอกสารอ้างอิง Apache ab อย่างเป็นทางการ
ApacheBench คืออะไรและมีที่มาอย่างไร
ab เป็นไคลเอนต์สำหรับทำ benchmarking ที่มาพร้อมกับ Apache HTTP Server ชื่อนี้ย่อมาจาก ApacheBench มันเปิดการเชื่อมต่อไปยัง URL เดียว ส่งคำขอได้เร็วเท่าที่การตั้งค่า concurrency ของคุณอนุญาต จับเวลาการตอบสนองแต่ละครั้ง และพิมพ์สรุปออกมา

มันวัดสิ่งหนึ่งได้ดี: จำนวนคำขอต่อวินาทีที่ endpoint เดียวสามารถให้บริการได้ และการกระจายเวลาตอบสนองภายใต้โหลด นั่นคือปริมาณงานและความหน่วงสำหรับ URL เดียว
สิ่งที่มันไม่ทำนั้นสำคัญไม่แพ้กัน ab ไม่ได้ตรวจสอบว่าเนื้อหาการตอบกลับถูกต้องหรือไม่ มันไม่ตรวจสอบ Schema หรือยืนยันค่าในฟิลด์ มันไม่ได้ทำตามขั้นตอนหลายขั้นตอน เช่น การเข้าสู่ระบบ จากนั้นดึงข้อมูล จากนั้นอัปเดต มันเรียกใช้ URL เดียวและนับจำนวน โปรดจำขอบเขตนี้ไว้ แล้ว ab จะยังคงมีประโยชน์ คาดหวังมากกว่านี้แล้วคุณจะผิดหวัง
หากคุณต้องการมุมมองที่กว้างขึ้นเกี่ยวกับสาขาวิชาที่ ab เข้ากันได้ โปรดดู การทดสอบโหลด API คืออะไร และ เหตุใดเวลาตอบสนองของ API จึงมีความสำคัญ
การติดตั้ง ab
ab มาพร้อมกับยูทิลิตี้ของ Apache ชื่อแพ็คเกจจะแตกต่างกันไปตามแพลตฟอร์ม
บน Debian และ Ubuntu ติดตั้งแพ็คเกจ apache2-utils:
sudo apt-get update
sudo apt-get install -y apache2-utils
บน CentOS, RHEL และ Fedora แพ็คเกจคือ httpd-tools:
# CentOS 7
sudo yum install -y httpd-tools
# Fedora and CentOS 8+
sudo dnf install -y httpd-tools
บน macOS, ab มีอยู่แล้วเนื่องจากระบบมาพร้อมกับ Apache ลองตรวจสอบดู:
ab -V
คุณควรจะเห็นบรรทัดเวอร์ชันเช่น Version 2.3 หากไม่พบคำสั่งบน macOS ให้ติดตั้งผ่าน Apache formula ของ Homebrew เมื่อ ab -V แสดงเวอร์ชัน คุณก็พร้อมใช้งาน
การรันการทดสอบโหลดพื้นฐาน
แฟล็กสองตัวที่คุณจะใช้ทุกครั้งคือ -n และ -c
-n requestsกำหนดจำนวนคำขอทั้งหมดที่จะดำเนินการ ค่าเริ่มต้นคือคำขอเดียว ซึ่งไม่ได้บอกอะไรเลย ดังนั้นควรตั้งค่านี้เสมอ-c concurrencyกำหนดจำนวนคำขอที่จะทำงานพร้อมกัน ค่าเริ่มต้นคือหนึ่ง ซึ่งหมายถึงการทำงานแบบอนุกรมทั้งหมด
นี่คือคำขอ 1000 รายการ โดย 50 รายการในแต่ละครั้ง สำหรับ JSON endpoint:
ab -n 1000 -c 50 https://api.example.com/v1/users
โปรดสังเกตเส้นทางต่อท้าย ab ต้องการ URL แบบเต็มที่มีเส้นทาง หากคุณชี้ไปที่โฮสต์เปล่าที่ไม่มีเส้นทาง มันจะเกิดข้อผิดพลาด สำหรับ root ให้ใช้เครื่องหมายทับต่อท้าย: https://api.example.com/
ไคลเอนต์จริงจะใช้การเชื่อมต่อ TCP ซ้ำแทนที่จะเปิดการเชื่อมต่อใหม่สำหรับแต่ละคำขอ เพิ่ม -k เพื่อเปิดใช้งาน HTTP KeepAlive เพื่อให้ ab ใช้การเชื่อมต่อซ้ำภายในเซสชัน:
ab -n 1000 -c 50 -k https://api.example.com/v1/users
การรันด้วย -k มักจะใกล้เคียงกับพฤติกรรมของเบราว์เซอร์หรือไคลเอนต์ API ที่ทำงานได้ดี เนื่องจากจะหลีกเลี่ยงการจ่ายค่าใช้จ่ายในการตั้งค่าการเชื่อมต่อในทุกคำขอ เปรียบเทียบตัวเลขทั้งสองเพื่อดูว่าความหน่วงของคุณเป็นค่าใช้จ่ายในการเชื่อมต่อมากน้อยเพียงใด
คุณยังสามารถจำกัดการทำงานด้วยเวลาแทนที่จะเป็นจำนวนได้ -t กำหนดจำนวนวินาทีสูงสุด และหมายถึง -n 50000 ภายใน ดังนั้นการทดสอบจะหยุดเมื่อถึงขีดจำกัดใดที่คุณพบก่อน:
ab -t 30 -c 50 -k https://api.example.com/v1/users
นั่นจะทำงานได้สูงสุด 30 วินาทีที่ concurrency 50 มีประโยชน์เมื่อคุณต้องการอ่านข้อมูลตามระยะเวลาที่กำหนด แทนที่จะเป็นจำนวนที่กำหนด
การทดสอบ POST endpoint
งาน API ส่วนใหญ่ไม่ใช่ GET ในการทดสอบ POST ให้ใส่เนื้อหาคำขอลงในไฟล์และส่งผ่านด้วย -p คุณต้องตั้งค่าประเภทเนื้อหาด้วย -T ด้วย มิฉะนั้นเซิร์ฟเวอร์จะปฏิเสธเนื้อหา
สร้าง payload:
cat > payload.json <<<'EOF'
{"name": "Ada Lovelace", "email": "ada@example.com"}
EOF
จากนั้นส่ง:
ab -n 500 -c 25 -k \
-p payload.json \
-T application/json \
https://api.example.com/v1/users
แฟล็ก -p ใช้ระบุชื่อไฟล์ที่มีเนื้อหา POST แฟล็ก -T ใช้ตั้งค่าส่วนหัว Content-Type ประเภทเนื้อหาเริ่มต้นคือ text/plain ซึ่งเกือบจะไม่ใช่สิ่งที่ JSON API ต้องการ ดังนั้นควรตั้งค่า -T application/json อย่างชัดเจน
หาก endpoint ของคุณต้องการการยืนยันตัวตน (auth) หรือส่วนหัวอื่นๆ ให้เพิ่มด้วย -H ทำซ้ำแฟล็กสำหรับส่วนหัวแต่ละรายการ:
ab -n 500 -c 25 -k \
-p payload.json \
-T application/json \
-H "Authorization: Bearer YOUR_TOKEN" \
https://api.example.com/v1/users
สำหรับการทบทวนวิธีการสร้างเนื้อหาคำขอ JSON ด้วยตนเอง โปรดดู วิธีการ POST ข้อมูล JSON ด้วย curl เนื้อหาเดียวกันนี้สามารถใช้เป็นไฟล์ payload ของ ab ได้
การอ่านผลลัพธ์
การรันหนึ่งครั้งจะแสดงชุดตัวเลข นี่คือตัวอย่างที่ตัดทอนแล้ว:
Concurrency Level: 50
Time taken for tests: 4.212 seconds
Complete requests: 1000
Failed requests: 0
Non-2xx responses: 0
Requests per second: 237.42 [#/sec] (mean)
Time per request: 210.598 [ms] (mean)
Time per request: 4.212 [ms] (mean, across all concurrent requests)
Transfer rate: 142.31 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 5 18 9.4 16 64
Processing: 22 189 41.2 182 310
Waiting: 21 177 39.8 171 295
Total: 31 207 42.7 201 338
Percentage of the requests served within a certain time (ms)
50% 201
66% 221
75% 236
90% 268
95% 291
99% 324
100% 338 (longest request)
โปรดอ่านฟิลด์เหล่านี้ก่อน:
- Requests per second (คำขอต่อวินาที) คือหัวข้อปริมาณงานของคุณ มันคือจำนวนคำขอหารด้วยเวลาทั้งหมด ยิ่งสูงยิ่งดี
- Failed requests (คำขอที่ล้มเหลว) และ Non-2xx responses (การตอบสนองที่ไม่ใช่ 2xx) จะบอกคุณว่าเซิร์ฟเวอร์สามารถจัดการโหลดได้จริงหรือไม่ หรือเริ่มเกิดข้อผิดพลาด หากจำนวนคำขอต่อวินาทีสูงแต่ครึ่งหนึ่งของการตอบสนองเป็น 500 ก็ไม่มีความหมายอะไร ตรวจสอบสองสิ่งนี้เสมอก่อนที่คุณจะเชื่อถือตัวเลขปริมาณงาน
- Time per request (เวลาต่อคำขอ) จะปรากฏสองครั้ง บรรทัดแรกคือเวลาเฉลี่ยที่ผู้ใช้คนเดียวรอ (concurrency คูณเวลาทั้งหมด หารด้วยจำนวนคำขอ) บรรทัดที่สองซึ่งมีป้ายกำกับว่า "across all concurrent requests" คือค่าเฉลี่ยของช่วงเวลาระหว่างคำขอที่เสร็จสมบูรณ์ ตัวเลขแรกคือสิ่งที่ผู้ใช้รู้สึก
ตาราง Percentage of the requests served within a certain time (เปอร์เซ็นต์ของคำขอที่ให้บริการภายในเวลาที่กำหนด) เป็นส่วนที่มีประโยชน์ที่สุด มันคือการแจกแจงตามเปอร์เซ็นไทล์ แถว 50% คือค่ามัธยฐานของคุณ แถว 95% และ 99% แสดงถึงส่วนที่ช้าที่สุด (slow tail) ในตัวอย่าง ครึ่งหนึ่งของคำขอเสร็จสิ้นภายใน 201ms แต่ 1% ใช้เวลา 324ms หรือนานกว่านั้น Tail latency คือส่วนที่ผู้ใช้จริงได้รับผลกระทบ ดังนั้นควรให้ความสำคัญกับเปอร์เซ็นไทล์ที่ 95 และ 99 มากกว่าค่าเฉลี่ย
ต้องการตัวเลขดิบต่อคำขอสำหรับสร้างแผนภูมิหรือไม่? เพิ่ม -e results.csv เพื่อเขียนไฟล์ CSV ที่มีคู่เปอร์เซ็นไทล์-เวลา หรือ -g results.tsv สำหรับไฟล์ที่เข้ากันได้กับ gnuplot
เมื่อใดที่ ab ไม่ใช่เครื่องมือที่เหมาะสมอีกต่อไป
ab ถูกออกแบบมาให้มีขอบเขตที่แคบโดยเจตนา ขีดจำกัดของมันควรถูกระบุอย่างชัดเจนเพื่อที่คุณจะได้ไม่นำไปใช้ในทางที่ผิด
- หนึ่ง URL ต่อการรัน.
abจะเรียกใช้ endpoint เดียวเท่านั้น มันไม่สามารถสร้างสคริปต์ลำดับการทำงานเช่น การยืนยันตัวตน การสร้างทรัพยากร แล้วอ่านกลับมาได้ การเดินทางของผู้ใช้จริงนั้นเกี่ยวข้องกับหลาย endpoint ตามลำดับ และabไม่มีความเข้าใจในเรื่องนั้น - ไม่มีการตรวจสอบความถูกต้อง.
abจะนับรหัสสถานะและความยาวของไบต์ มันไม่ได้แยกวิเคราะห์ JSON ของคุณหรือยืนยันว่าฟิลด์มีค่าเท่ากับค่าที่คาดหวัง การตอบสนองอาจผิดพลาดในโครงสร้างแต่ยังคงถูกนับว่าเป็นความสำเร็จ ตัวเลขโหลดไม่ใช่สิ่งทดแทนชุดการทดสอบที่ผ่าน - การจัดการ HTTP ที่ล้าสมัย. เอกสารทางการระบุว่า
abไม่ได้ใช้ HTTP/1.x อย่างเต็มรูปแบบ และยอมรับเฉพาะรูปแบบการตอบสนองที่คาดหวังบางรูปแบบเท่านั้น ไม่มีการรองรับ HTTP/2 สำหรับเซิร์ฟเวอร์ที่มีพฤติกรรมแตกต่างกันภายใต้ HTTP/2,abจะไม่สะท้อนถึงสิ่งนั้น - โหลดจากเครื่องเดียว.
abทำงานจากเครื่องเดียวและกระบวนการเดียว เมื่อเกิน concurrency ระดับหนึ่ง คุณจะวัดขีดจำกัดของไคลเอนต์ของคุณเองแทนที่จะเป็นของเซิร์ฟเวอร์ เอกสารยังเตือนด้วยว่าการแยกวิเคราะห์ของabเองอาจกลายเป็นคอขวดในโปรไฟล์ได้
ไม่มีสิ่งใดในนี้ที่ทำให้ ab แย่ มันทำให้ ab เป็นเครื่องมือเฉพาะ: เป็นเครื่องมือตรวจสอบปริมาณงานที่รวดเร็วสำหรับ endpoint เดียว เมื่อคุณต้องการขั้นตอนการทำงานที่เป็นสคริปต์, โหลดแบบกระจาย, หรือ HTTP/2 ให้ใช้เครื่องมือที่สร้างขึ้นมาเพื่อสิ่งเหล่านั้น JMeter จัดการสถานการณ์ที่มีหลายขั้นตอนและการรันแบบกระจาย และยังมี เครื่องมือทดสอบโหลดที่ครอบคลุมมากขึ้น หากคุณกำลังเปรียบเทียบตัวเลือกต่างๆ
การทดสอบฟังก์ชันเหมาะกับที่ใด
ปริมาณงานเป็นหนึ่งในแกน ความถูกต้องเป็นอีกแกนหนึ่ง ซึ่ง ab ไม่ได้ครอบคลุม ก่อนที่คุณจะทดสอบโหลด endpoint คุณต้องการทราบว่ามันส่งคืนข้อมูลที่ถูกต้องในรูปแบบที่เหมาะสมภายใต้สภาวะปกติ นั่นคือการทดสอบฟังก์ชันและการทดสอบสัญญา (contract testing) ซึ่งเป็นงานที่แตกต่างกัน
นี่คือจุดที่แพลตฟอร์ม API แบบเต็มเข้ามามีบทบาทเคียงคู่กับ ab Apidog ช่วยให้คุณสร้างสถานการณ์การทดสอบด้วยการยืนยันแบบภาพ เชื่อมโยงคำขอเข้ากับขั้นตอนหลายขั้นตอน และตรวจสอบการตอบสนองกับ Schema ของคุณ ซึ่งเป็นสิ่งที่ ab ไม่สามารถทำได้โดยการออกแบบ คุณบันทึกสถานการณ์เหล่านั้นเพียงครั้งเดียวและเรียกใช้ได้ทุกที่
สำหรับการผสานรวมอย่างต่อเนื่อง (continuous integration) Apidog CLI สามารถรันสถานการณ์ที่คุณบันทึกไว้ได้โดยไม่มีส่วนต่อประสานกับผู้ใช้ (headless) ติดตั้งด้วย Node:
npm install -g apidog-cli
จากนั้นเรียกใช้สถานการณ์หรือชุดการทดสอบที่บันทึกไว้กับสภาพแวดล้อมที่เลือก โดยจะสร้างรายงานที่ CI ของคุณสามารถเก็บถาวรได้:
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-r cli,html,junit
แฟล็ก -t กำหนดเป้าหมายสถานการณ์ โฟลเดอร์ หรือชุดการทดสอบที่บันทึกไว้ด้วย ID แฟล็ก -e เลือกสภาพแวดล้อม แฟล็ก -r เลือกหนึ่งหรือหลายตัวรายงานจาก cli, html, json และ junit สำหรับการรันที่ขับเคลื่อนด้วยข้อมูล ให้เพิ่ม -d (หรือ --iteration-data) พร้อมกับพาธไฟล์ข้อมูลหรือ ID ข้อมูลการทดสอบ CLI เป็นแบบ headless และรันสถานการณ์ที่บันทึกไว้ ดังนั้นจึงเหมาะกับทุกขั้นตอน CI ที่สามารถรัน Node ได้ มันไม่ใช่ตัวส่งคำขอและไม่ใช่ตัวสร้างโหลด แต่มันรันการทดสอบฟังก์ชันที่ ab ไม่ได้ถูกออกแบบมาให้รัน
การตั้งค่าที่ดีควรใช้ทั้งสองอย่าง เรียกใช้สถานการณ์ Apidog เพื่อพิสูจน์ว่า endpoint ถูกต้อง เรียกใช้ ab เพื่อพิสูจน์ว่ามันเร็วพอ สำหรับด้านความถูกต้อง โปรดดู คู่มือการทดสอบประสิทธิภาพ Apidog และ บทช่วยสอนการทดสอบประสิทธิภาพ API ทั่วไป
คำถามที่พบบ่อย
ApacheBench ใช้ได้กับเซิร์ฟเวอร์ Apache เท่านั้นหรือไม่?
ไม่ แม้จะมีชื่อนี้ แต่ ab สามารถส่งคำขอ HTTP และ HTTPS ธรรมดาไปยังเซิร์ฟเวอร์ใดก็ได้ มันทำงานได้กับ Nginx, Node, Go, Python หรือโฮสต์ใดๆ ที่สื่อสารด้วย HTTP ความเชื่อมโยงกับ Apache เพียงแค่ว่าเครื่องมือนี้มาพร้อมกับ Apache HTTP Server
ฉันควรใช้ concurrency และจำนวนคำขอเท่าใด?
เริ่มจากน้อยๆ แล้วค่อยๆ เพิ่มขึ้น ลองใช้ -n 1000 -c 10 จากนั้นเพิ่ม -c เป็น 25, 50, 100 และสังเกตว่า Requests per second หยุดเพิ่มขึ้นและ Failed requests เริ่มปรากฏที่ใด จุดเปลี่ยนนั้นคือจุดที่ endpoint เกิดภาวะอิ่มตัวโดยประมาณ ปรับ concurrency สูงสุดของคุณให้เข้ากับการจราจรจริงที่คาดไว้ แทนที่จะเลือกตัวเลขกลมๆ ใหญ่ๆ
ทำไมคำขอที่ล้มเหลวของฉันถึงสูง ทั้งที่ API ทำงานได้ดี?
ab จะทำเครื่องหมายคำขอว่าล้มเหลวหากความยาวการตอบสนองแตกต่างกันไประหว่างคำขอ ซึ่งเป็นเรื่องปกติสำหรับ JSON แบบไดนามิก เพิ่มแฟล็ก -l เพื่อหยุดนับความแตกต่างของความยาวเป็นความล้มเหลว จากนั้นตรวจสอบบรรทัด Non-2xx responses เพื่อดูว่ามีข้อผิดพลาดจริงอยู่เบื้องล่างหรือไม่
ab สามารถทดสอบ endpoint ที่ต้องการโทเค็นการเข้าสู่ระบบได้หรือไม่?
ได้ หากคุณมีโทเค็นอยู่แล้ว ส่งผ่านด้วย -H "Authorization: Bearer YOUR_TOKEN" สิ่งที่ ab ทำไม่ได้คือการเข้าสู่ระบบก่อนเพื่อรับโทเค็นใหม่ แล้วจึงนำไปใช้ นั่นคือขั้นตอนการทำงานที่มีหลายขั้นตอน และคุณต้องการเครื่องมือที่อิงตามสถานการณ์เช่น Apidog สำหรับการทำเช่นนั้น
ab รองรับ HTTP/2 หรือไม่?
ไม่ ab ใช้ HTTP/1.x และตามเอกสารทางการระบุว่ายังไม่รองรับเต็มรูปแบบด้วยซ้ำ หากพฤติกรรมของเซิร์ฟเวอร์ของคุณภายใต้ HTTP/2 มีความสำคัญ ให้ใช้เครื่องมือโหลดที่รองรับ HTTP/2 แทน
