Bạn đã triển khai một endpoint. Nó chạy tốt trên trình duyệt của bạn, nhưng điều đó chưa trả lời được các câu hỏi quan trọng: khi 400 người truy cập cùng lúc thì độ trễ có ổn định không? P99 có tăng vọt không? Server chịu được 1.000 request/giây hay bắt đầu nghẽn ở mức 300?
wrk giúp bạn đo các con số đó. Đây là công cụ dòng lệnh dùng để tạo tải HTTP lên một URL và báo cáo tốc độ phản hồi của server dưới tải.
wrk là gì và khi nào nên dùng?
wrk là công cụ benchmark HTTP hiện đại. Nó tạo tải từ một máy đa lõi duy nhất, đo thông lượng request và độ trễ phản hồi của server.
Bên dưới, wrk dùng nhiều thread kết hợp với event loop có khả năng mở rộng:
-
epolltrên Linux -
kqueuetrên macOS
Vì vậy, một instance wrk có thể tạo ra lượng tải lớn mà không cần nhiều máy load generator.
Dùng wrk khi bạn cần trả lời các câu hỏi như:
- Endpoint này duy trì được bao nhiêu request/giây?
- Độ trễ trung bình, P90, P99 là bao nhiêu?
- Server có ổn định dưới tải kéo dài không?
- Thay đổi code mới làm hiệu năng tốt hơn hay tệ hơn?
Lưu ý: wrk là công cụ benchmark, không phải bộ kiểm thử chức năng. Nó đo tốc độ, nhưng không xác nhận JSON response đúng hay sai, status code có phải 200 hay không, hoặc API có tuân thủ contract không.
Nếu bạn cần nền tảng về các khái niệm load testing, xem thêm hướng dẫn kiểm thử tải API.
Cài đặt wrk
macOS
Cách đơn giản nhất là dùng Homebrew:
brew install wrk
Trên Apple Silicon, nên ưu tiên binary từ Homebrew. Việc build từ source có thể gặp lỗi với LuaJIT ARM64.
Kiểm tra cài đặt:
wrk --version
Linux
Trên Linux, bạn thường cần build từ source.
Cài toolchain và OpenSSL headers:
sudo apt-get install build-essential libssl-dev git -y
Clone repo và build:
git clone https://github.com/wg/wrk.git
cd wrk
make
Sau khi build, binary wrk nằm trong thư mục hiện tại. Di chuyển nó vào PATH:
sudo cp wrk /usr/local/bin
Kiểm tra:
wrk --version
Chạy benchmark đầu tiên
Cú pháp cơ bản:
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html
Trong đó:
-
-t,--threads: số thread hệ điều hành mà wrk tạo ra. -
-c,--connections: tổng số kết nối HTTP được giữ mở. -
-d,--duration: thời gian chạy benchmark.
Ví dụ trên nghĩa là:
- 12 thread
- 400 connection
- chạy trong 30 giây
- benchmark URL
http://127.0.0.1:8080/index.html
Một cấu hình thực tế hơn khi test API local:
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Nên bật --latency trong hầu hết các lần chạy để xem phân phối độ trễ, đặc biệt là P90 và P99.
Các flag quan trọng
-t: số thread
Ví dụ:
-t8
Điểm khởi đầu hợp lý là một thread cho mỗi CPU core.
Nếu máy chạy wrk có 8 core:
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Nếu CPU của máy client bị đầy, kết quả benchmark có thể phản ánh giới hạn của máy tạo tải thay vì giới hạn của server.
-c: số connection
Ví dụ:
-c200
Flag này mô phỏng số client đồng thời. -c200 nghĩa là wrk giữ 200 kết nối HTTP mở trong suốt bài test.
Tăng dần connection để tìm điểm server bắt đầu bão hòa:
wrk -t8 -c50 -d30s --latency http://localhost:3000/api/users
wrk -t8 -c100 -d30s --latency http://localhost:3000/api/users
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
wrk -t8 -c400 -d30s --latency http://localhost:3000/api/users
Quan sát:
- Requests/sec còn tăng không?
- P99 có tăng mạnh không?
- Timeout hoặc error có xuất hiện không?
- CPU, memory, DB connection pool của server ra sao?
-d: thời lượng test
Ví dụ:
-d30s
wrk chấp nhận các giá trị như:
-d10s
-d30s
-d2m
-d1h
Dùng vài giây cho smoke test nhanh. Dùng 30 giây đến vài phút để có kết quả ổn định hơn.
--latency
Luôn bật flag này khi bạn quan tâm trải nghiệm người dùng:
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Trung bình thường che giấu tail latency. P99 mới là con số giúp bạn thấy một phần nhỏ request đang bị chậm đến mức nào.
--timeout
Dùng để giới hạn thời gian chờ response:
wrk -t8 -c200 -d30s --latency --timeout 2s http://localhost:3000/api/users
Nếu request không nhận được response trong 2 giây, wrk ghi nhận timeout.
Đọc kết quả wrk
Ví dụ output:
Running 5s test @ http://10.135.232.163:3000
2 threads and 5 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.82ms 2.64ms 26.68ms 85.81%
Req/Sec 550.90 202.40 0.98k 68.00%
5494 requests in 5.01s, 1.05MB read
Requests/sec: 1096.54
Transfer/sec: 215.24KB
Đọc từ dưới lên.
Requests/sec
Requests/sec: 1096.54
Đây là thông lượng trung bình: server xử lý được khoảng 1.096 request/giây.
Dùng con số này để so sánh:
- trước và sau khi tối ưu code
- giữa các endpoint
- giữa các cấu hình server
- giữa HTTP và HTTPS
- giữa các mức concurrency
Transfer/sec
Transfer/sec: 215.24KB
Đây là lượng dữ liệu truyền mỗi giây.
Chỉ số này hữu ích khi:
- response payload lớn
- bạn nghi ngờ bị giới hạn bởi network bandwidth
- benchmark endpoint trả file hoặc dữ liệu lớn
Latency
Latency 3.82ms 2.64ms 26.68ms 85.81%
Ý nghĩa:
-
Avg: độ trễ trung bình -
Stdev: độ lệch chuẩn -
Max: độ trễ cao nhất -
+/- Stdev: phần trăm mẫu nằm trong một độ lệch chuẩn
Trong ví dụ:
- trung bình:
3.82ms - cao nhất:
26.68ms
Max cao hơn nhiều so với Avg cho thấy một số request chậm hơn đáng kể so với phần lớn request.
Req/Sec
Req/Sec 550.90 202.40 0.98k 68.00%
Đây là số request/giây theo từng thread, kèm phân phối của nó.
Nếu giá trị này dao động mạnh, có thể server hoặc client load generator đang không ổn định.
Xem phân phối độ trễ với --latency
Khi thêm --latency, wrk in thêm phần phân vị:
Latency Distribution
50% 3.21ms
75% 4.86ms
90% 7.09ms
99% 14.13ms
Cách đọc:
- P50: 50% request hoàn thành trong
3.21ms - P75: 75% request hoàn thành trong
4.86ms - P90: 90% request hoàn thành trong
7.09ms - P99: 99% request hoàn thành trong
14.13ms
P99 là chỉ số nên theo dõi kỹ. Nếu average thấp nhưng P99 cao, một nhóm nhỏ người dùng vẫn gặp response chậm.
Gửi POST request với Lua script
Mặc định wrk gửi request GET.
Để gửi POST, body hoặc custom header, dùng Lua script với flag -s.
Tạo file post.lua:
wrk.method = "POST"
wrk.body = '{"name": "Ada", "role": "engineer"}'
wrk.headers["Content-Type"] = "application/json"
Chạy benchmark:
wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/users
Trong script:
-
wrk.method: HTTP method -
wrk.body: request body -
wrk.headers: bảng chứa HTTP headers
Gửi form-encoded POST
Ví dụ body dạng application/x-www-form-urlencoded:
wrk.method = "POST"
wrk.body = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
Chạy:
wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/form
Thêm header bằng -H
Nếu chỉ cần thêm một hoặc hai header, bạn có thể dùng -H thay vì Lua script:
wrk -t4 -c100 -d30s \
-H "Authorization: Bearer TOKEN123" \
--latency \
http://localhost:3000/api/protected
Thêm nhiều header:
wrk -t4 -c100 -d30s \
-H "Authorization: Bearer TOKEN123" \
-H "X-Tenant-Id: tenant_123" \
--latency \
http://localhost:3000/api/protected
Quy tắc thực tế:
- Dùng
-Hcho header đơn giản. - Dùng Lua script khi cần body, method khác
GET, hoặc logic tùy biến theo từng request.
Một workflow benchmark thực tế
Thay vì chạy một lệnh duy nhất, hãy tăng tải theo từng bước.
Ví dụ:
URL="http://localhost:3000/api/users"
wrk -t8 -c50 -d30s --latency "$URL"
wrk -t8 -c100 -d30s --latency "$URL"
wrk -t8 -c200 -d30s --latency "$URL"
wrk -t8 -c400 -d30s --latency "$URL"
Ghi lại cho mỗi lần chạy:
- Requests/sec
- P50
- P90
- P99
- timeout/error nếu có
- CPU server
- memory server
- DB CPU/query latency
- connection pool usage
Mục tiêu không chỉ là tìm request/giây cao nhất. Bạn cần tìm mức tải mà hệ thống vẫn giữ được latency ổn định.
Một dấu hiệu bão hòa thường gặp:
- Requests/sec không tăng thêm dù tăng
-c - P99 tăng mạnh
- timeout bắt đầu xuất hiện
- CPU server hoặc database đạt ngưỡng cao
- queue trong app hoặc DB tăng
Giới hạn: wrk không kiểm tra tính đúng đắn
wrk cho bạn biết server phản hồi nhanh như thế nào. Nó không cho bạn biết response có đúng hay không.
Ví dụ: nếu endpoint trả HTTP 500 cho mọi request, wrk vẫn có thể báo Requests/sec rất cao. Lý do là wrk chỉ đo giao dịch HTTP hoàn thành, không xác thực:
- status code
- response body
- JSON schema
- business logic
- API contract
Lỗi thậm chí có thể trông “nhanh” hơn, vì server từ chối request sớm và làm ít việc hơn.
Vì vậy:
- wrk trả lời: “Endpoint có đủ nhanh dưới tải không?”
- Test chức năng trả lời: “Endpoint có đúng không?”
Bạn cần cả hai. Đây là lý do nhiều nhóm kết hợp benchmark tool với bộ kiểm thử chức năng.
Vị trí của Apidog trong workflow kiểm thử
Một workflow rõ ràng nên có hai lớp.
Bước 1: xác thực hành vi API
Trước khi đo tốc độ, hãy xác nhận endpoint hoạt động đúng.
Trong Apidog, bạn có thể tạo test scenario để gửi request thật và kiểm tra:
- status code
- field trong JSON
- response schema
- logic nghiệp vụ
- dữ liệu truyền giữa các bước
- cùng một scenario trên nhiều environment
Lớp này giúp bắt lỗi mà wrk không phát hiện, ví dụ endpoint trả 500 nhưng vẫn phản hồi rất nhanh.
Bước 2: benchmark thông lượng
Sau khi hành vi đã đúng, dùng wrk để benchmark các endpoint đó dưới concurrency và tải liên tục.
Apidog cũng có kiểm thử hiệu năng tích hợp nếu bạn muốn giữ kiểm thử chức năng và kiểm thử tải trong cùng một nơi. Còn wrk phù hợp khi bạn cần benchmark dòng lệnh nhanh, thô và dễ script hóa.
Chạy Apidog CLI trong CI
Lớp kiểm thử chức năng nên chạy trong CI, không chỉ trên máy cá nhân.
Cài Apidog CLI:
npm install -g apidog-cli
Chạy scenario hoặc test suite đã lưu theo ID:
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-r cli,html,junit
Ý nghĩa:
-
-t: ID của scenario, folder hoặc test suite -
-e: ID environment -
-r: định dạng report, ví dụcli,html,json,junit
Report JUnit có thể được tích hợp vào hầu hết hệ thống CI để kiểm tra pass/fail.
Với test chạy theo dữ liệu, thêm -d hoặc --iteration-data:
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-d ./data.csv \
-r cli,html,junit
Apidog CLI chạy các scenario và test suite đã lưu. Nó là công cụ headless để kiểm tra tính đúng đắn, không phải load generator.
Một cách phân chia hợp lý:
Apidog CLI -> kiểm tra API đúng hay sai
wrk -> đo API nhanh hay chậm dưới tải
Bạn có thể xem thêm hướng dẫn CI/CD với CLI, hướng dẫn GitHub Actions, hoặc tài liệu tham khảo CLI đầy đủ.
Câu hỏi thường gặp
wrk khác gì ab, ApacheBench?
Cả hai đều tạo tải HTTP và báo cáo request/giây.
Khác biệt chính:
- wrk đa luồng và dùng event loop.
- ab đơn luồng.
- wrk thường tạo được tải lớn hơn từ một máy duy nhất.
- Cả hai đều không xác thực tính đúng đắn của response.
Nếu bạn cần benchmark concurrency cao từ một máy, wrk thường phù hợp hơn.
Nên dùng bao nhiêu thread và connection?
Bắt đầu với một thread cho mỗi CPU core.
Ví dụ máy có 8 core:
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Sau đó tăng dần -c:
-c50
-c100
-c200
-c400
Nếu throughput không tăng nhưng latency tăng mạnh, có thể server đã bão hòa.
Nếu CPU trên máy chạy wrk đạt 100%, kết quả có thể bị giới hạn bởi client load generator.
wrk có test được HTTPS không?
Có.
Chỉ cần dùng URL https://:
wrk -t8 -c200 -d30s --latency https://example.com/api/users
HTTPS có thêm chi phí TLS, nên thông lượng có thể thấp hơn HTTP thuần. Trên Linux, đây là lý do bạn cần libssl-dev khi build wrk.
wrk có xác thực status code hoặc response body không?
Không.
wrk đo thời gian và đếm HTTP transaction hoàn thành. Nó không kiểm tra status code, JSON body hoặc schema.
Nếu cần xác thực tính đúng đắn, hãy dùng bộ kiểm thử chức năng như test suite chạy qua Apidog CLI, sau đó dùng wrk để đo thông lượng.
Một bài load test nên chạy bao lâu?
Tối thiểu nên chạy đủ lâu để vượt qua các hiệu ứng khởi động như cache lạnh hoặc JIT warm-up.
Gợi ý:
-
5sđến10s: kiểm tra nhanh -
30s: mặc định hợp lý - vài phút: tốt hơn để phát hiện suy giảm dưới tải kéo dài
- lâu hơn: hữu ích khi tìm memory leak hoặc degradation chậm
Ví dụ mặc định:
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Khi nào nên nghi ngờ kết quả wrk?
Hãy kiểm tra lại nếu:
- endpoint đang trả lỗi nhưng Requests/sec vẫn cao
- máy chạy wrk bị CPU 100%
- network giữa client và server bị giới hạn
- database hoặc dependency bên ngoài không giống production
- thời lượng test quá ngắn
- không bật
--latency - chỉ nhìn average latency mà bỏ qua P99
Benchmark tốt không chỉ là một con số Requests/sec. Nó phải đi kèm latency distribution, error/timeout và metrics từ server.
Top comments (0)