Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

JMeter — Thread Group, Sampler, Listener

Mở đầu — vì sao bài này quan trọng

Nếu ví JMeter như một chiếc xe, thì ba thành phần bạn học trong bài này — Thread Group, Sampler, và Listener — chính là động cơ, tay lái và đồng hồ táp-lô. Thiếu một trong ba, bạn hoặc không đi được, hoặc đi mà không biết mình đang chạy nhanh hay chậm. Đây là bộ ba nền tảng: hầu như mọi kịch bản kiểm thử hiệu năng bằng JMeter, dù đơn giản hay phức tạp đến đâu, đều được dựng lên từ ba khối này.

Ở bài trước bạn đã cài JMeter và mở được giao diện. Nhưng một Test Plan trống rỗng thì chưa làm được gì. Bài này dạy bạn cách lắp ráp một bài test thực sự: khai báo bao nhiêu người dùng ảo, họ gửi request gì đến đâu, và làm sao bạn nhìn thấy kết quả. Khi nắm chắc ba thành phần này, bạn có thể tự tin nhìn vào cây Test Plan của bất kỳ ai và hiểu ngay họ đang mô phỏng điều gì.

Rất nhiều người mới học JMeter mắc lỗi vì không hiểu vai trò từng thành phần — họ thêm Listener bừa bãi làm test chậm giật, hoặc cấu hình Thread Group sai khiến 500 "người dùng" thực chất chỉ là 5 người chạy đi chạy lại. Hiểu đúng bản chất từ đầu sẽ tiết kiệm cho bạn hàng chục giờ gỡ lỗi về sau.

Khái niệm cốt lõi

Trước hết, hãy hình dung cấu trúc cây (tree) của một Test Plan tối thiểu:

Test Plan
├── Thread Group (1)             ← số người dùng ảo + kịch bản chạy
│   ├── HTTP Header Manager       ← header dùng chung (Config Element)
│   ├── HTTP Request (Sampler)    ← request thực tế gửi đi
│   └── View Results Tree (Listener) ← xem kết quả từng request

Ba thành phần trong bài nằm ở ba tầng vai trò khác nhau: Thread Group điều phối, Sampler hành động, Listener quan sát.

Thread Group — bộ điều phối người dùng ảo

Thread Group là nơi bạn định nghĩa kịch bản tải. Trong JMeter, mỗi "người dùng ảo" (virtual user) được biểu diễn bằng một thread. Ba tham số quan trọng nhất:

  • Number of Threads (users): số người dùng ảo chạy song song. Đặt 100 nghĩa là mô phỏng 100 người cùng dùng hệ thống.
  • Ramp-up period (seconds): khoảng thời gian để JMeter khởi động dần toàn bộ thread. Ví dụ 100 threads với ramp-up 10 giây nghĩa là cứ mỗi 0,1 giây có thêm 1 người dùng bắt đầu chạy. Ramp-up giúp bạn tránh việc dội 100 request cùng một mili-giây — điều không thực tế và dễ gây hiểu lầm về hiệu năng.
  • Loop Count: mỗi thread lặp lại kịch bản bao nhiêu lần. Đặt 5 nghĩa là mỗi người dùng thực hiện toàn bộ chuỗi request 5 lượt. Tích chọn "Infinite" khi bạn muốn chạy theo thời gian thay vì theo số lần lặp.
Một công thức bạn nên nhớ: tổng số request ≈ Number of Threads × Loop Count × số Sampler trong nhóm. Nếu có 100 threads, loop 5 lần, mỗi lần gọi 3 Sampler, bạn sẽ tạo ra khoảng 1.500 request. Nắm được phép nhân này giúp bạn ước lượng tải trước khi bấm chạy.

Thread Group còn có phần Action to be taken after a Sampler error — quyết định điều gì xảy ra khi một request lỗi: tiếp tục (Continue), dừng thread, hay dừng cả test. Với hầu hết bài load test, để "Continue" là hợp lý vì bạn muốn thấy toàn cảnh tỷ lệ lỗi chứ không dừng ngay khi gặp lỗi đầu tiên.

Sampler — hành động gửi request

Sampler là thành phần thực sự tạo ra tải lên hệ thống. Mỗi Sampler đại diện cho một hành động cụ thể mà người dùng ảo thực hiện. Trong kiểm thử web, loại phổ biến nhất là HTTP Request Sampler. Các trường cần điền:

  • Protocol: http hoặc https.
  • Server Name or IP: tên miền, ví dụ shopee.vn (không kèm https://).
  • Port Number: thường bỏ trống (mặc định 80/443).
  • HTTP Request Method: GET, POST, PUT, DELETE...
  • Path: đường dẫn, ví dụ /api/v2/product/get.
  • Parameters / Body Data: tham số query hoặc phần thân (body) cho request POST.
Một mẹo tổ chức tốt: đặt phần Protocol/Server chung vào một HTTP Request Defaults (Config Element) để không phải gõ lại tên miền ở từng Sampler. Nhưng bản thân Config Element không phải Sampler — nó chỉ cung cấp giá trị mặc định.

Ngoài HTTP, JMeter còn có nhiều loại Sampler khác: JDBC Request (truy vấn database), FTP Request, JMS, TCP Sampler... Trong bài này ta tập trung vào HTTP Request vì nó chiếm phần lớn nhu cầu thực tế.

Listener — con mắt quan sát kết quả

Listener không tạo tải. Nhiệm vụ của nó là thu thập và hiển thị kết quả từ các Sampler. Vài Listener bạn sẽ dùng thường xuyên:

  • View Results Tree: hiển thị chi tiết từng request/response (headers, body, mã trạng thái). Cực kỳ hữu ích khi gỡ lỗi kịch bản, nhưng tuyệt đối không dùng khi chạy tải thật vì nó lưu toàn bộ dữ liệu response vào RAM, làm chậm và có thể treo JMeter.
  • Summary Report / Aggregate Report: hiển thị số liệu tổng hợp — số mẫu (samples), thời gian phản hồi trung bình, phần trăm lỗi, throughput. Đây là thứ bạn nhìn để đánh giá hiệu năng.
  • Simple Data Writer: ghi kết quả thô ra file .jtl để phân tích sau, tốn rất ít tài nguyên.
Điểm mấu chốt: Listener có thể "ngốn" tài nguyên nếu dùng sai. Bạn sẽ hiểu sâu cách đọc những con số này ở các bài về metrics và reporting; ở đây chỉ cần nắm vai trò và cách thêm chúng vào cây.

Tình huống thực tế

Ví dụ 1 — Tiki mô phỏng trang danh mục sản phẩm

Giả sử đội QA của một sàn thương mại điện tử kiểu Tiki muốn kiểm tra API trả về danh sách sản phẩm ngành hàng "Điện thoại" trước đợt khuyến mãi. Họ dựng Test Plan với Thread Group: 200 threads, ramp-up 40 giây, loop 10. Sampler là một HTTP GET tới /api/v2/products?category=dien-thoai&page=1. Ban đầu họ gắn luôn View Results Tree để xem response.

Sau 3 phút chạy, JMeter trên máy tester bắt đầu đơ, RAM leo lên 6 GB. Con số throughput trên báo cáo thấp bất thường. Bạn có nhận ra vấn đề? Chính View Results Tree đang lưu 200 × 10 = 2.000 response đầy đủ vào bộ nhớ, khiến chính công cụ đo trở thành nút thắt cổ chai, chứ không phải server bị kiểm thử.

Bài học: trong lúc dựng kịch bản, dùng View Results Tree với 1–2 threads để kiểm tra request đúng chưa. Khi chạy tải thật, gỡ bỏ nó, chỉ giữ Summary Report và Simple Data Writer. Kết quả đo mới phản ánh đúng năng lực server.

Ví dụ 2 — Ngân hàng số hiểu sai ramp-up

Một fintech ở TP.HCM cần kiểm thử API đăng nhập trước khi ra mắt tính năng mới. Tester đặt 500 threads nhưng ramp-up = 0. Kết quả: 500 request đăng nhập dội vào server trong chưa đầy một giây. Server trả về hàng loạt lỗi 503 Service Unavailable, và cả đội hốt hoảng tưởng hệ thống không chịu nổi 500 người dùng.

Thực tế, 500 người dùng thật không bao giờ đăng nhập trong cùng một mili-giây. Khi tester chỉnh ramp-up lên 100 giây (5 người/giây, sát với lưu lượng thực tế giờ cao điểm), tỷ lệ lỗi về gần 0 và thời gian phản hồi ổn định. Vấn đề không nằm ở server, mà ở kịch bản tải phi thực tế.

Bài học: ramp-up không phải tham số làm cho đẹp — nó định hình hình dạng của tải. Ramp-up = 0 tạo ra một cú "spike" (dội tải) chứ không phải load test thông thường. Chọn ramp-up phản ánh cách người dùng thật đến với hệ thống.

Ví dụ 3 — Startup giáo dục và phép nhân bị bỏ quên

Một startup edtech dựng Test Plan gồm 50 threads, loop 20, bên trong Thread Group có 4 Sampler mô phỏng luồng: mở trang khóa học → xem chi tiết → thêm giỏ hàng → thanh toán. Trưởng nhóm hỏi "test này bắn bao nhiêu request?". Nhiều bạn đoán 50. Con số đúng là 50 × 20 × 4 = 4.000 request. Vì không tính trước, họ vô tình gửi 4.000 lượt thanh toán thử vào môi trường staging, kích hoạt hàng nghìn email xác nhận đơn hàng ảo tới hộp thư của cả team.

Bài học: luôn nhẩm phép nhân Threads × Loop × số Sampler trước khi bấm chạy, và với các Sampler có tác dụng phụ (gửi email, tạo đơn, trừ tồn kho), hãy cân nhắc kỹ dữ liệu và môi trường.

Hướng dẫn từng bước

Ta sẽ dựng một Test Plan tối thiểu nhưng hoàn chỉnh, kiểm thử một trang chủ.

  • Tạo Test Plan. Mở JMeter, mặc định đã có sẵn node "Test Plan" ở gốc cây. Đặt tên gợi nhớ, ví dụ "Homepage Load Test".
  • Thêm Thread Group. Chuột phải vào Test Plan → AddThreads (Users)Thread Group. Điền: Number of Threads = 20, Ramp-up period = 10, Loop Count = 5. Đây là mức nhẹ, an toàn để tập.
  • (Khuyến nghị) Thêm HTTP Request Defaults. Chuột phải Thread Group → AddConfig ElementHTTP Request Defaults. Điền Protocol https và Server Name example.com. Nhờ vậy các Sampler sau chỉ cần điền Path.
  • Thêm HTTP Header Manager (tùy chọn nhưng nên có). AddConfig ElementHTTP Header Manager. Thêm header dùng chung như User-Agent hoặc Accept: application/json. Header này áp dụng cho mọi Sampler trong nhóm.
  • Thêm Sampler. Chuột phải Thread Group → AddSamplerHTTP Request. Nếu đã có Defaults, chỉ cần điền Method = GET và Path = /. Đặt tên Sampler rõ ràng, ví dụ "GET Homepage".
  • Thêm Listener để gỡ lỗi. Chuột phải Thread Group → AddListenerView Results Tree. Tạm thời để đó.
  • Chạy thử nhỏ. Bấm nút Start (biểu tượng tam giác xanh). Mở View Results Tree, kiểm tra request có mã 200, response đúng như mong đợi không. Nếu thấy lỗi, sửa Sampler tại đây.
  • Thêm Listener tổng hợp. Khi kịch bản đã đúng, thêm Summary Report để đọc số liệu trung bình, throughput, tỷ lệ lỗi.
  • Chuẩn bị cho tải thật. Vô hiệu hóa hoặc xóa View Results Tree (chuột phải → Disable). Nếu muốn lưu kết quả thô, thêm Simple Data Writer trỏ tới file results.jtl. Đến đây bạn đã có một bộ khung chuẩn: Thread Group điều phối, Sampler tạo tải, Listener quan sát.

Lỗi thường gặp & mẹo

  • Để View Results Tree bật khi chạy tải lớn. Đây là lỗi số một khiến JMeter chậm và kết quả sai lệch. Chỉ dùng để debug với vài thread; tắt trước khi chạy thật.
  • Nhầm ramp-up = 0 là "chạy nhanh hơn". Nó không nhanh hơn, nó biến load test thành spike test. Trừ khi bạn cố ý test dội tải, hãy đặt ramp-up hợp lý.
  • Quên rằng Loop Count nhân với Number of Threads. Đặt 100 threads loop 100 lần là 10.000 lượt qua kịch bản — dễ vượt xa ý định ban đầu. Luôn nhẩm phép nhân.
  • https:// vào ô Server Name. Ô này chỉ nhận tên miền hoặc IP; protocol để ở ô riêng. Gõ sai sẽ gây lỗi DNS khó hiểu.
  • Không dùng HTTP Request Defaults. Với Test Plan nhiều Sampler, việc lặp lại tên server ở từng chỗ khiến bảo trì cực khổ. Config Element giúp bạn sửa một nơi, áp dụng mọi nơi.
  • Đặt tên mặc định cho Sampler. Khi có 10 Sampler đều tên "HTTP Request", báo cáo trở nên vô nghĩa. Đặt tên mô tả để dòng nào trong Summary Report cũng đọc được.
  • Mẹo bật/tắt nhanh: thay vì xóa một thành phần khi thử nghiệm, dùng Disable (chuột phải) để tạm ẩn nó khỏi lần chạy mà vẫn giữ cấu hình.
  • Mẹo tổ chức: dùng một Thread Group cho mỗi nhóm hành vi người dùng khác nhau (ví dụ nhóm "khách vãng lai" và nhóm "người đã đăng nhập") thay vì nhồi tất cả vào một nhóm.

Bài tập thực hành

  • Dựng bộ khung cơ bản. Tạo một Test Plan mới với Thread Group (10 threads, ramp-up 5s, loop 3), một HTTP Request Sampler GET tới một trang công khai bất kỳ (ví dụ https://httpbin.org/get), và một View Results Tree. Chạy và xác nhận tất cả request trả mã 200.
  • Kiểm chứng phép nhân. Với cấu hình ở bài 1, tính trước tổng số request bạn kỳ vọng. Chạy xong, mở Summary Report và đối chiếu cột "# Samples" có khớp với con số bạn nhẩm không. Giải thích vì sao khớp hoặc lệch.
  • Thí nghiệm ramp-up. Giữ nguyên 10 threads, loop 3, nhưng chạy hai lần: một lần ramp-up = 0, một lần ramp-up = 30. So sánh thời gian phản hồi và tỷ lệ lỗi giữa hai lần. Viết 3 câu nhận xét về ảnh hưởng của ramp-up.
  • Tối ưu Listener. Thêm một Simple Data Writer ghi ra file .jtl, sau đó Disable View Results Tree. Chạy lại và quan sát mức tiêu thụ RAM của JMeter có giảm không.
  • Thêm hai Sampler. Bổ sung thêm 2 Sampler nữa vào Thread Group (ví dụ /get/headers của httpbin) và đặt tên rõ ràng cho từng cái. Chạy lại, kiểm tra Summary Report hiển thị đúng 3 dòng riêng biệt.

Tóm tắt

Ba thành phần cốt lõi của JMeter tạo thành một bộ ba phân vai rõ ràng: Thread Group điều phối (bao nhiêu người dùng ảo, khởi động dần thế nào, lặp bao nhiêu lần), Sampler hành động (thực sự gửi request tạo tải lên hệ thống), và Listener quan sát (thu thập, hiển thị kết quả mà không tạo tải).

Hãy khắc ghi mấy nguyên tắc: nhẩm phép nhân Threads × Loop × số Sampler để biết mình bắn bao nhiêu request; dùng ramp-up để mô phỏng cách người dùng thật đến với hệ thống thay vì dội tải; và không bao giờ để View Results Tree bật khi chạy tải lớn — dùng Summary Report và Simple Data Writer thay thế. Config Element như HTTP Request Defaults và Header Manager giúp cây Test Plan gọn gàng, dễ bảo trì.

Khi đã thành thạo lắp ráp ba khối này, bạn đã có nền tảng vững để bước sang các bài tiếp theo về Variables, CSV Data Set, Extractors và Assertions — những công cụ biến một kịch bản tĩnh thành một kịch bản động, thông minh, sát với hành vi người dùng thật.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi