Menu
ESC

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

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

Đang tải...

JMeter và k6 Basics

Performance Testing with JMeter and k6 Bài 2/60

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

Ở bài trước, bạn đã hiểu Performance Testing là một triết lý: ta muốn biết hệ thống chịu được bao nhiêu người dùng, phản hồi nhanh chậm ra sao, và gãy ở đâu. Nhưng triết lý thì cần công cụ để biến thành hành động. Trong toàn bộ khóa học này, hai công cụ sẽ đi cùng bạn từ đầu đến cuối là JMeterk6. Chúng giống như hai "chiếc búa" trong hộp đồ nghề của một Performance Engineer: cùng đóng đinh, nhưng cầm khác nhau, hợp với những loại đinh khác nhau.

Bài này là bài "làm quen". Mục tiêu không phải để bạn viết được một kịch bản test hoàn chỉnh (điều đó sẽ đến ở các bài sau, khi ta mổ xẻ từng Thread Group, từng Sampler, từng Threshold). Mục tiêu ở đây là để bạn có bản đồ tổng thể: JMeter là gì, k6 là gì, chúng khác nhau ở tư duy nào, cấu trúc một bài test trong mỗi công cụ trông ra sao, và khi nào bạn nên với tay lấy công cụ nào.

Tại sao phải nắm cả hai? Vì thị trường Việt Nam đang ở giai đoạn chuyển giao. Rất nhiều ngân hàng, công ty tài chính, doanh nghiệp lớn (Techcombank, VPBank, các công ty gia công như FPT Software, TMA Solutions) vẫn dùng JMeter vì nó đã ăn sâu vào quy trình, có sẵn thư viện kịch bản, và team QA quen thuộc. Nhưng các startup và công ty product hiện đại (Momo, VNG, Tiki, Shopee VN) ngày càng nghiêng về k6 vì nó "code-first", hợp với văn hóa DevOps và CI/CD. Một Performance Engineer giỏi ở Việt Nam năm 2026 gần như bắt buộc phải đọc và viết được cả hai. Nếu bạn chỉ biết một, bạn tự giới hạn một nửa cơ hội việc làm.

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

JMeter — người khổng lồ lâu đời của thế giới Java

Apache JMeter là một công cụ mã nguồn mở, viết bằng Java, ra đời từ năm 1998. Điều đó có nghĩa là nó đã "sống" hơn 25 năm — một tuổi đời khổng lồ trong thế giới phần mềm. Chính vì lâu đời, JMeter cực kỳ trưởng thành: cộng đồng đông, plugin nhiều, tài liệu và câu hỏi trên Stack Overflow gần như phủ hết mọi tình huống bạn gặp.

Đặc điểm nhận diện lớn nhất của JMeter là nó có giao diện đồ họa (GUI). Bạn thiết kế bài test bằng cách kéo-thả, click chuột, điền vào các ô — giống như dựng một cây thư mục. Điều này khiến JMeter rất dễ tiếp cận với người mới, đặc biệt là các bạn QA không xuất thân lập trình. Bạn không cần viết một dòng code nào cũng có thể tạo ra một bài test gửi 500 request đến website.

JMeter hỗ trợ rất nhiều giao thức, không chỉ HTTP:

  • HTTP/HTTPS — test web và REST API (phổ biến nhất).
  • JDBC — test hiệu năng truy vấn trực tiếp vào database.
  • SOAP / REST — test các web service kiểu cũ và mới.
  • FTP, JMS, TCP, LDAP, SMTP — những giao thức mà k6 không hỗ trợ hoặc hỗ trợ yếu.
Đây là điểm mạnh mà nhiều người bỏ qua: nếu bạn phải test một hệ thống ngân hàng lõi (core banking) giao tiếp qua JMS, hay cần đo tốc độ một câu query nặng trực tiếp trên Oracle, JMeter gần như là lựa chọn duy nhất trong hai công cụ này.

Một điểm quan trọng bạn cần khắc cốt ghi tâm từ hôm nay: JMeter dùng GUI để THIẾT KẾ, nhưng dùng CLI (dòng lệnh) để CHẠY thật. GUI ngốn rất nhiều RAM và CPU cho việc vẽ đồ thị real-time, nên khi chạy load test thật với hàng nghìn user, ta luôn chạy ở chế độ Non-GUI (dòng lệnh). Chi tiết chuyện này sẽ có nguyên một bài riêng (Bài 11), nhưng nguyên tắc thì bạn phải nhớ ngay: GUI để thiết kế, CLI để bắn.

Cấu trúc một Test Plan trong JMeter

Trong JMeter, mọi thứ được tổ chức theo dạng cây (tree), gốc là Test Plan. Hãy hình dung nó như một củ hành với các lớp:

  • Test Plan — gốc của mọi thứ, chứa biến toàn cục và cấu hình chung.
- Thread Group — mô phỏng một nhóm người dùng ảo. "Thread" ở đây chính là một "user ảo". Nếu bạn đặt 100 thread, JMeter mô phỏng 100 người dùng cùng lúc. - Sampler — hành động thật sự gửi đi, ví dụ "HTTP Request" đến /api/login. Đây là "cú click chuột" của user ảo. - Logic Controller — điều khiển luồng (lặp lại, rẽ nhánh if/else). - Config Element — cấu hình dùng chung, ví dụ đọc dữ liệu từ file CSV. - Assertion — kiểm tra kết quả có đúng không (ví dụ status code phải là 200). - Timer — thêm thời gian chờ giữa các request để giống người thật. - Listener — nơi thu thập và hiển thị kết quả (đồ thị, bảng, file).

Bạn chưa cần hiểu sâu từng thành phần — các bài 8, 9, 10 sẽ đào rất kỹ. Việc bạn cần ở bài này là nhận ra cái cây khi mở JMeter lên: à, đây là Thread Group, đây là Sampler, đây là Listener. Chỉ cần nhìn ra bộ khung.

k6 — kẻ thách thức hiện đại, viết bằng JavaScript

k6 ra đời năm 2016 (do công ty Load Impact phát triển, sau này được Grafana Labs mua lại). Nó sinh ra để trả lời một câu hỏi mà giới developer bực bội với JMeter: "Tại sao tôi phải click chuột hàng giờ và lưu ra file XML khổng lồ, thay vì viết một đoạn code gọn gàng, đưa vào Git và review như code bình thường?"

k6 được viết bằng ngôn ngữ Go (nên chạy rất nhanh, tốn ít tài nguyên), nhưng bạn viết kịch bản test bằng JavaScript. Đây là điểm mấu chốt cần hiểu cho đúng: lõi công cụ là Go, nhưng "ngôn ngữ" bạn dùng để mô tả bài test là JavaScript ES6. Bạn không cần biết Go.

Triết lý của k6 là "testing as code" (test dưới dạng mã):

  • Kịch bản test là một file .js — đưa vào Git, review qua Pull Request như bất kỳ code nào.
  • Không có GUI. Mọi thứ chạy bằng dòng lệnh: k6 run test.js.
  • Nhẹ và nhanh: một máy laptop k6 có thể tạo ra lượng tải mà JMeter cần vài máy mới làm nổi, vì k6 dùng "goroutine" của Go thay vì "thread" nặng nề của Java.
  • Sinh ra để sống trong CI/CD: chạy test tự động mỗi khi có commit, rồi "đánh trượt" bản build nếu hiệu năng không đạt (chuyện này sẽ nói kỹ ở Bài 16 về Thresholds và Bài 27 về CI/CD).

Cấu trúc một script k6

Một file k6 tối giản trông như thế này:

import http from 'k6/http';
import { sleep } from 'k6';

export const options = { vus: 10, // 10 virtual users (user ảo) duration: '30s' // chạy trong 30 giây };

export default function () { http.get('https://test.k6.io'); sleep(1); // giả lập người dùng nghỉ 1 giây }

Chỉ vậy thôi. Đọc từ trên xuống:

  • import — nhập các module cần dùng (thư viện HTTP, hàm sleep).
  • options — cấu hình bài test: bao nhiêu user ảo (VU - Virtual User), chạy bao lâu.
  • default function — thân bài test, mỗi VU sẽ lặp đi lặp lại đoạn này. Đây tương đương với "Thread Group + Sampler" của JMeter, gói gọn trong một hàm.
Bạn thấy sự đối lập chưa? Cùng một ý tưởng "10 user ảo gọi vào một trang trong 30 giây", JMeter là một cái cây bạn dựng bằng chuột, còn k6 là 12 dòng code. Không cái nào "đúng" hơn — chúng phục vụ hai kiểu người và hai bối cảnh khác nhau.

Bảng so sánh nhanh để bạn ghim vào đầu

Tiêu chíJMeterk6
Nền tảngJavaGo (viết test bằng JavaScript)
Giao diệnCó GUI (kéo-thả)Không GUI (chỉ CLI)
Cách định nghĩa testCây thành phần (.jmx / XML)File code (.js)
Đưa vào Git & reviewKhó (file XML rối)Dễ (như code thường)
Giao thứcHTTP, JDBC, SOAP, FTP, JMS, TCP...Chủ yếu HTTP, WebSocket, gRPC
Mức tiêu tốn tài nguyênNặngNhẹ
Phù hợp CI/CDĐược, nhưng phải cấu hình thêmSinh ra để làm việc này
Đường học ban đầuDễ với người không codeCần biết JavaScript cơ bản
Lưu ý: bài 40 trong khóa này sẽ có nguyên một "ma trận ra quyết định" chi tiết để chọn giữa JMeter và k6. Ở đây ta chỉ dựng cái nhìn tổng quan.

Tình huống thực tế

Tình huống 1: Ngân hàng số ở TP.HCM chọn JMeter vì lý do "không ngờ tới"

Một ngân hàng số tại TP.HCM (giả định, tạm gọi là "SaigonBank Digital") cần test hiệu năng cho tính năng chuyển khoản liên ngân hàng. Đội QA có 6 người, trong đó chỉ 1 người biết lập trình. Ban đầu, trưởng nhóm định dùng k6 vì "nghe nói hiện đại". Nhưng khi khảo sát kỹ, họ phát hiện ba vấn đề: (1) hệ thống core banking giao tiếp một phần qua JMS — k6 không hỗ trợ; (2) họ cần đo trực tiếp thời gian chạy của các câu query trên Oracle qua JDBC; (3) 5/6 thành viên không viết được JavaScript.

Kết quả: họ chọn JMeter. Với JMeter, 5 bạn QA không biết code vẫn dựng được kịch bản bằng cách kéo-thả JDBC Sampler và JMS Sampler. Họ đo được một câu query báo cáo giao dịch mất tới 4,2 giây ở mức 200 giao dịch/giây — một con số không thể chấp nhận, buộc team backend phải thêm index.

Bài học rút ra: Đừng chọn công cụ theo "trend". Hãy chọn theo giao thức hệ thống dùngkỹ năng thực tế của đội. JMeter thắng ở đây không phải vì nó "tốt hơn", mà vì nó khớp với hai ràng buộc cứng: giao thức đa dạng và đội ngũ ít người code.

Tình huống 2: Startup thương mại điện tử chọn k6 để "gác cổng" mỗi lần deploy

Một startup thương mại điện tử ở Hà Nội (giả định, "MuaNhanh") có đội kỹ sư 12 người, dùng GitLab CI để deploy nhiều lần mỗi ngày. Nỗi đau của họ: có lần một developer sửa một API giỏ hàng, vô tình làm thời gian phản hồi tăng từ 180ms lên 950ms, nhưng không ai phát hiện cho đến khi khách hàng phàn nàn hai ngày sau.

Họ đưa k6 vào pipeline. Mỗi lần có Pull Request, GitLab tự chạy k6 run cart-test.js. Trong file test, họ đặt một "cửa gác" (threshold): nếu 95% request giỏ hàng chậm hơn 300ms, bài test fail, và Pull Request bị chặn merge tự động. Từ đó, mọi lần code làm chậm API đều bị bắt ngay tại chỗ, trước khi lên production. File .js được review chung với code tính năng, ai cũng đọc hiểu được.

Bài học rút ra: Sức mạnh của k6 không nằm ở chỗ nó "bắn tải giỏi hơn" JMeter, mà ở chỗ nó hòa tan được vào quy trình phát triển. Test trở thành một phần của code, chạy tự động, làm "người gác cổng" chất lượng. Với đội ngũ biết code và làm CI/CD, đây là lợi thế mà GUI của JMeter rất khó theo kịp.

Tình huống 3: Công ty gia công dùng CẢ HAI

Một công ty gia công phần mềm ở Đà Nẵng (giả định, "DaNang Software") làm dự án cho nhiều khách hàng khác nhau. Với khách hàng ngân hàng Nhật vẫn giữ hệ thống cũ, họ dùng JMeter vì đó là công cụ hợp đồng yêu cầu và có sẵn kho kịch bản .jmx. Với một khách hàng SaaS ở Singapore chạy microservices trên Kubernetes, họ dùng k6 vì khách yêu cầu test chạy trong pipeline GitHub Actions.

Điều thú vị: cùng một Performance Engineer tên Minh phụ trách cả hai dự án. Buổi sáng anh mở JMeter GUI dựng Thread Group cho ngân hàng, buổi chiều anh viết script k6 cho dự án Singapore. Chính vì thành thạo cả hai mà lương của Minh cao hơn 30% so với đồng nghiệp chỉ biết một công cụ.

Bài học rút ra: Trong thực tế nghề nghiệp, "JMeter hay k6" thường không phải câu hỏi đúng. Câu hỏi đúng là "JMeter k6 — dùng cái nào cho bối cảnh nào". Việc bạn học cả hai trong khóa này chính là đang tự trang bị lợi thế cạnh tranh đó.

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

Đây là bước làm quen, chưa phải test thật. Mục tiêu: chạm tay vào cả hai công cụ để cảm nhận sự khác biệt. (Việc cài đặt chi tiết JMeter sẽ có ở Bài 7; đây chỉ là "nếm thử".)

Bước 1 — Nếm thử JMeter (dùng GUI):

  • Đảm bảo máy đã có Java (JMeter chạy trên Java). Gõ java -version để kiểm tra.
  • Tải Apache JMeter từ trang chủ, giải nén, chạy file bin/jmeter.sh (macOS/Linux) hoặc bin/jmeter.bat (Windows).
  • Khi GUI mở lên, bạn thấy sẵn một Test Plan trống. Chuột phải vào nó → Add → Threads (Users) → Thread Group.
  • Chuột phải vào Thread Group vừa tạo → Add → Sampler → HTTP Request. Điền server name (ví dụ test.k6.io), path /.
  • Chuột phải vào Thread Group → Add → Listener → View Results Tree.
  • Bấm nút Play (tam giác xanh). Xem kết quả xuất hiện trong Listener.
Cảm nhận: bạn vừa dựng một bài test không viết một dòng code nào. Đó là bản chất của JMeter.

Bước 2 — Nếm thử k6 (dùng CLI):

  • Cài k6 (ví dụ trên macOS: brew install k6; Windows dùng choco install k6).
  • Tạo một file tên hello.js với nội dung ví dụ ở phần trên (import http, options với vus và duration, default function gọi http.get).
  • Mở terminal, gõ: k6 run hello.js.
  • Xem k6 in ra bảng thống kê thẳng trên màn hình: số request, thời gian phản hồi trung bình, p95, tỉ lệ lỗi.
Cảm nhận: không có cửa sổ nào bật lên, không kéo-thả gì. Bạn viết code, gõ lệnh, có kết quả ngay trong terminal. Đó là bản chất của k6.

Bước 3 — So sánh cảm giác: Sau khi làm cả hai, hãy tự hỏi: với cách làm việc và kỹ năng của bạn, cái nào tự nhiên hơn? Không có câu trả lời sai. Nhưng câu trả lời của bạn sẽ hé lộ bạn hợp làm việc trong môi trường nào hơn.

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

Lỗi 1: Chạy load test thật bằng JMeter GUI. Đây là lỗi kinh điển của người mới. GUI ngốn tài nguyên khủng khiếp cho việc vẽ đồ thị. Khi bạn chạy 1000 user trong GUI, chính JMeter (chứ không phải hệ thống đích) sẽ là thứ gãy trước, cho ra số liệu sai bét. Mẹo: GUI chỉ để thiết kế và test thử vài user. Chạy thật luôn dùng Non-GUI (jmeter -n -t test.jmx -l result.jtl). Chi tiết ở Bài 11.

Lỗi 2: Tưởng k6 viết bằng Go nên phải học Go. Không. Lõi k6 là Go, nhưng bạn viết test bằng JavaScript. Nếu bạn biết viết một đoạn JS cơ bản (khai báo hàm, gọi API), bạn viết được k6.

Lỗi 3: Nghĩ rằng phải chọn một công cụ "vĩnh viễn". Nhiều bạn mất thời gian tranh cãi "học JMeter hay k6". Câu trả lời của mentor: học cả hai ở mức cơ bản trước, rồi để ngữ cảnh dự án quyết định. Chi phí học công cụ thứ hai thấp hơn nhiều so với chi phí bỏ lỡ cơ hội vì chỉ biết một.

Lỗi 4: Nhầm "thread" (JMeter) và "VU" (k6) là hai khái niệm khác nhau. Về ý niệm chúng giống nhau: đều là "một người dùng ảo". JMeter gọi là thread, k6 gọi là virtual user (VU). Đừng để tên gọi khác nhau làm bạn rối.

Mẹo vàng: Ngay từ hôm nay, hãy tập thói quen hỏi ba câu trước khi chọn công cụ: (1) Hệ thống dùng giao thức gì? (2) Đội tôi có biết code không? (3) Có cần chạy tự động trong CI/CD không? Ba câu này gần như luôn cho bạn câu trả lời đúng.

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

  • Nhận diện bộ khung: Mở JMeter GUI, dựng thủ công một Test Plan có: 1 Thread Group (5 user), 1 HTTP Request đến test.k6.io, 1 Listener "View Results Tree". Chạy và chụp màn hình kết quả. Ghi chú lại: đâu là thread, đâu là sampler, đâu là listener.
  • Viết script k6 đầu tiên: Tạo file hello.js gọi http.get đến https://test.k6.io với 5 VU trong 20 giây. Chạy k6 run hello.js. Trong bảng kết quả, tìm và ghi lại ba con số: http_req_duration trung bình, giá trị p(95), và http_req_failed.
  • So sánh viết tay: Kẻ một bảng hai cột (JMeter | k6). Với mỗi tiêu chí sau, tự điền: nền tảng, có GUI không, cách lưu bài test, mức độ dễ đưa vào Git. Không nhìn lại bài — kiểm tra xem bạn đã nhớ được bao nhiêu.
  • Ra quyết định: Viết 3–4 câu cho tình huống sau: "Công ty bạn có hệ thống REST API thuần, đội 8 kỹ sư đều biết JavaScript, dùng GitHub Actions deploy mỗi ngày." Bạn chọn JMeter hay k6? Vì sao? (Gợi ý: dùng ba câu hỏi vàng ở phần mẹo.)

Tóm tắt

  • JMeter là công cụ Java lâu đời, có GUI kéo-thả, hỗ trợ rất nhiều giao thức (HTTP, JDBC, SOAP, FTP, JMS...). Bài test được tổ chức thành cây: Test Plan → Thread Group → Sampler → Listener/Assertion/Timer. Nhớ quy tắc: GUI để thiết kế, CLI (Non-GUI) để chạy thật.
  • k6 là công cụ hiện đại viết bằng Go nhưng bạn viết test bằng JavaScript. Không có GUI, chạy hoàn toàn bằng dòng lệnh, theo triết lý "test dưới dạng code" — hợp với Git, review và đặc biệt là CI/CD. Cấu trúc gọn: importoptions (vus, duration) → default function.
  • "Thread" của JMeter và "VU" của k6 cùng nghĩa: một người dùng ảo.
  • Chọn công cụ dựa trên ba câu hỏi: giao thức hệ thống, kỹ năng đội ngũ, nhu cầu CI/CD — không dựa theo trend.
  • Trong nghề thật ở Việt Nam, biết cả hai là lợi thế cạnh tranh rõ rệt. Đây mới là bài làm quen; các bài sau sẽ đào sâu từng thành phần của cả JMeter lẫn k6.