wrk: Cách kiểm thử tải API từ dòng lệnh

Tìm hiểu cách kiểm tra tải một API bằng wrk từ dòng lệnh: cài đặt, các cờ cho luồng và kết nối, đọc kết quả độ trễ, và các yêu cầu POST thông qua Lua.

Ashley Innocent

Ashley Innocent

6 tháng 7 2026

wrk: Cách kiểm thử tải API từ dòng lệnh

Apidog cho doanh nghiệp

Triển khai tại chỗ

SSO & RBAC

Tuân thủ SOC 2

Khám phá Apidog Enterprise

Bạn đã triển khai một endpoint. Nó hoạt động trong trình duyệt của bạn. Nhưng bạn không biết điều gì sẽ xảy ra khi 400 người truy cập nó cùng lúc. Độ trễ có ổn định không, hay phân vị thứ chín mươi chín tăng vọt? Liệu máy chủ có thể xử lý 1.000 yêu cầu mỗi giây, hay nó sẽ sập ở mức 300?

wrk sẽ trả lời điều đó. Đây là một công cụ dòng lệnh nhỏ gửi nhiều lưu lượng HTTP đến một URL và báo cáo tốc độ phản hồi của máy chủ dưới tải đó.

nút

wrk là gì và khi nào nên sử dụng nó

wrk là một công cụ benchmark HTTP hiện đại. Nó tạo tải từ một máy đa lõi duy nhất và đo độ trễ cũng như tốc độ yêu cầu mà máy chủ trả về. Nó sử dụng đa luồng cùng với một vòng lặp sự kiện có thể mở rộng (epoll trên Linux, kqueue trên macOS), vì vậy một phiên bản có thể đẩy nhiều lưu lượng mà không cần một cụm máy tạo tải.

Hãy sử dụng wrk khi bạn muốn các số liệu hiệu suất thô:

wrk là một công cụ benchmark, không phải là một bộ công cụ kiểm thử. Nó đo tốc độ. Nó không kiểm tra xem phần thân JSON có đúng không, mã trạng thái là 200 hay hợp đồng API có được tuân thủ không. Hãy ghi nhớ sự khác biệt đó. Chúng ta sẽ quay lại vấn đề này gần cuối, vì nó thay đổi cách bạn tích hợp wrk vào quy trình kiểm thử thực tế. Nếu bạn muốn có cái nhìn tổng quan hơn trước, hướng dẫn kiểm thử tải API này bao gồm các khái niệm mà wrk áp dụng.

Cài đặt wrk

macOS

Homebrew có một binary dựng sẵn, đây là cách dễ nhất:

brew install wrk

Trên Apple Silicon, điều này rất quan trọng. Việc xây dựng từ mã nguồn có thể gặp sự cố với LuaJIT ARM64, vì vậy binary của Homebrew sẽ giúp bạn tránh khỏi rắc rối đó.

Linux (xây dựng từ mã nguồn)

Không có gói apt chính thức, vì vậy bạn phải tự xây dựng nó. Trước tiên, hãy cài đặt toolchain và OpenSSL headers:

sudo apt-get install build-essential libssl-dev git -y

Sau đó clone và biên dịch:

git clone https://github.com/wg/wrk.git
cd wrk
make

Thao tác đó tạo ra một binary wrk trong thư mục hiện tại. Hãy di chuyển nó vào PATH của bạn để bạn có thể gọi nó từ bất cứ đâu:

sudo cp wrk /usr/local/bin

Xác nhận nó chạy:

wrk --version

Lệnh cơ bản

Đây là cấu trúc của mỗi lần chạy wrk:

wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html

Có bốn điều đang xảy ra. Hãy cùng phân tích các cờ (flags).

Hai cờ nữa bạn sẽ sử dụng thường xuyên:

Một lần chạy bạn sẽ thường xuyên sử dụng trông như thế này:

wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users

Tám luồng, 200 kết nối, 30 giây, với phân phối độ trễ đầy đủ được in ở cuối.

Đọc kết quả

wrk in ra một báo cáo cô đọng. Dưới đây là một lần chạy thực tế đối với một dịch vụ nhỏ:

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

Hãy đọc từ dưới lên, vì hai dòng cuối cùng là tiêu đề chính.

Requests/sec là thông lượng: số lượng yêu cầu mà máy chủ hoàn thành mỗi giây trung bình. Ở đây là 1.096. Đây là con số bạn so sánh giữa các lần chạy và giữa các thay đổi mã.

Transfer/sec là băng thông: lượng dữ liệu được truyền mỗi giây. Hữu ích khi các payload lớn hoặc bạn nghi ngờ mình bị giới hạn bởi băng thông chứ không phải bởi CPU.

Bây giờ là bảng Thread Stats, mô tả phân phối chứ không chỉ là giá trị trung bình:

Cột +/- Stdev cho bạn biết tỷ lệ phần trăm các mẫu nằm trong một độ lệch chuẩn. Tỷ lệ phần trăm thấp hơn có nghĩa là sự phân tán rộng hơn, ít dự đoán được hơn.

Dòng 5494 requests in 5.01s xác nhận tổng khối lượng mà lần chạy thực sự đã đẩy.

Khi bạn thêm --latency, wrk in ra một khối phân vị để bạn có thể thấy trực tiếp phần cuối (tail):

  Latency Distribution
     50%    3.21ms
     75%    4.86ms
     90%    7.09ms
     99%   14.13ms

Phân vị thứ 99 là con số cần theo dõi. Nếu 99% yêu cầu hoàn thành trong 14ms nhưng mức trung bình của bạn là 3.82ms, thì một trong một trăm người dùng đang phải đợi lâu hơn nhiều so với mức trung bình. Giá trị trung bình che giấu phần cuối. Các phân vị thì không.

Gửi yêu cầu POST và Header tùy chỉnh bằng Lua Script

Theo mặc định, wrk gửi các yêu cầu GET. Để gửi một yêu cầu POST, thêm phần thân (body) hoặc đặt các header tùy chỉnh, bạn truyền một Lua script với -s.

Tạo một tệp có tên post.lua:

wrk.method = "POST"
wrk.body   = '{"name": "Ada", "role": "engineer"}'
wrk.headers["Content-Type"] = "application/json"

Ba trường thực hiện công việc. wrk.method đặt động từ HTTP. wrk.body đặt phần thân yêu cầu. wrk.headers là một bảng trong đó mỗi khóa là tên header.

Chạy nó bằng cách trỏ -s vào script:

wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/users

Đối với POST được mã hóa biểu mẫu thay vì JSON, kho lưu trữ wrk cung cấp ví dụ chính xác này:

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

Bạn cũng có thể đặt header bằng cờ -H cho các trường hợp đơn giản hơn, mà không cần script:

wrk -t4 -c100 -d30s -H "Authorization: Bearer TOKEN123" --latency http://localhost:3000/api/protected

Sử dụng -H cho một hoặc hai header. Sử dụng Lua script khi bạn cần một phần thân (body), một phương thức không phải GET hoặc logic theo từng yêu cầu.

Giới hạn: wrk không kiểm tra tính đúng đắn

Đây là phần mà mọi người thường bỏ qua. wrk cho bạn biết máy chủ phản hồi nhanh như thế nào. Nó không cho bạn biết liệu câu trả lời có đúng hay không.

Chỉ wrk vào một endpoint trả về HTTP 500 trên mọi yêu cầu, và bạn sẽ nhận được một báo cáo trông gọn gàng với số yêu cầu mỗi giây cao. wrk đếm một giao dịch HTTP hoàn thành. Nó không xác nhận mã trạng thái, xác thực phần thân phản hồi dựa trên một schema, hoặc xác nhận API đã làm đúng những gì nó phải làm. Lỗi thậm chí có thể trông nhanh, vì một máy chủ từ chối yêu cầu sớm sẽ làm ít việc hơn cho mỗi yêu cầu.

Vì vậy, wrk trả lời "nó có đủ nhanh dưới tải không?" Nó không thể trả lời "nó có đúng không?". Cả hai câu hỏi đều quan trọng, và chúng cần các công cụ khác nhau. Một con số tải trên một endpoint bị lỗi là một con số bạn không nên tin tưởng. Đây chính xác là lý do tại sao các nhóm kết hợp một công cụ benchmark với một bộ kiểm thử chức năng. Một cái chứng minh tốc độ. Cái kia chứng minh hành vi.

Vị trí của Apidog và kiểm thử chức năng

Quy trình làm việc rõ ràng bao gồm hai lớp, được chạy theo thứ tự.

Đầu tiên, xác thực hành vi. Trước khi bạn quan tâm đến tốc độ của một endpoint, hãy xác nhận rằng nó đúng. Trong Apidog, bạn xây dựng các kịch bản kiểm thử gửi các yêu cầu thực tế và xác nhận những gì trả về: mã trạng thái, các trường JSON, schema phản hồi và logic nghiệp vụ. Bạn có thể nối chuỗi các yêu cầu, truyền dữ liệu giữa các bước và chạy cùng một kịch bản trên các môi trường khác nhau. Đây là lớp bắt được lỗi 500 mà wrk vẫn vui vẻ benchmark.

Sau đó, benchmark thông lượng. Khi hành vi đã được xác minh, hãy chạy wrk đối với các endpoint tương tự để xem chúng hoạt động như thế nào dưới sự đồng thời 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ữ công việc kiểm thử chức năng và tải ở cùng một nơi, nhưng wrk là một công cụ chuyên dụng tốt để benchmark dòng lệnh thô.

Lớp chức năng chạy trong CI, không chỉ trên máy tính xách tay của bạn. Apidog CLI là headless, vì vậy nó có thể được tích hợp vào bất kỳ bước pipeline nào có thể chạy Node. Cài đặt nó:

npm install -g apidog-cli

Sau đó chạy một kịch bản kiểm thử hoặc bộ kiểm thử đã lưu theo ID:

apidog run \
  --access-token "$APIDOG_ACCESS_TOKEN" \
  -t <scenarioOrSuiteId> \
  -e <environmentId> \
  -r cli,html,junit

-t là ID kịch bản, thư mục hoặc bộ kiểm thử để chạy. -e là ID môi trường. -r chọn định dạng báo cáo, một hoặc nhiều định dạng trong số cli, html, jsonjunit. Kết quả JUnit có thể được tích hợp trực tiếp vào hầu hết các hệ thống CI để kiểm tra pass/fail. Đối với các lần chạy dựa trên dữ liệu, hãy thêm -d (hoặc --iteration-data) với đường dẫn tệp hoặc ID dữ liệu kiểm thử để lặp lại cùng một kịch bản trên nhiều hàng đầu vào.

CLI chạy các kịch bản và bộ kiểm thử Apidog đã lưu. Nó là headless, không phải là trình gửi yêu cầu tương tác, và nó không phải là trình tạo tải. Nó là cổng kiểm tra tính đúng đắn. wrk là thước đo tốc độ. Chạy cổng kiểm tra tính đúng đắn trong pipeline của bạn (xem hướng dẫn CI/CD với CLI này hoặc hướng dẫn GitHub Actions để có cấu hình sao chép-dán), sau đó benchmark với wrk khi bạn cần các số liệu thông lượng. Tài liệu tham khảo CLI đầy đủ bao gồm các cờ còn lại.

Câu hỏi thường gặp

Sự khác biệt giữa wrk và ab (ApacheBench) là gì? Cả hai đều tạo tải HTTP và báo cáo số yêu cầu mỗi giây. wrk là đa luồng và sử dụng vòng lặp sự kiện, vì vậy nó tạo ra nhiều tải hơn từ một máy và xử lý độ đồng thời cao tốt hơn. ab là đơn luồng. Đối với tải nặng từ một máy duy nhất, wrk thường có khả năng mở rộng tốt hơn. Cả hai đều không kiểm tra tính đúng đắn của phản hồi.

Tôi nên sử dụng bao nhiêu luồng và kết nối? Bắt đầu với một luồng cho mỗi lõi CPU và đặt số kết nối theo mức độ đồng thời bạn muốn mô phỏng. Nếu bạn có 8 lõi và muốn mô phỏng 200 client đồng thời, hãy thử -t8 -c200. Quan sát máy client. Nếu bản thân wrk bị giới hạn bởi CPU, các con số của bạn phản ánh giới hạn của trình tạo tải, chứ không phải của máy chủ. Tăng số kết nối cho đến khi thông lượng không còn tăng nữa.

wrk có thể kiểm thử các endpoint HTTPS không? Có. Trỏ nó đến một URL https:// và wrk sẽ xử lý TLS. Đó là lý do tại sao bản dựng Linux cần libssl-dev. Các bắt tay TLS tăng chi phí CPU ở cả hai đầu, vì vậy hãy mong đợi thông lượng thô thấp hơn đối với HTTPS so với HTTP thuần túy.

wrk có xác thực phần thân phản hồi hoặc mã trạng thái không? Không. wrk đếm các giao dịch HTTP đã hoàn thành và đo thời gian. Nó không xác nhận mã trạng thái hoặc phần thân, vì vậy một endpoint trả về lỗi vẫn có thể có số yêu cầu mỗi giây cao. Sử dụng một bộ kiểm thử chức năng, chẳng hạn như một bộ được chạy thông qua Apidog CLI, để xác minh tính đúng đắn, sau đó sử dụng wrk để đo thông lượng.

Một bài kiểm thử tải nên chạy trong bao lâu? Đủ lâu để vượt qua các hiệu ứng khởi động như cache lạnh và biên dịch JIT. Vài giây là tốt cho một lần kiểm tra nhanh, nhưng từ 30 giây đến vài phút sẽ cho ra các con số ổn định hơn và làm lộ rõ sự suy giảm chỉ xuất hiện dưới tải liên tục. Sử dụng -d30s làm mặc định hợp lý và kéo dài thời gian khi bạn đang tìm kiếm các rò rỉ chậm.

Thực hành thiết kế API trong Apidog

Khám phá cách dễ dàng hơn để xây dựng và sử dụng API