Tháng 11 vừa qua, một anh chàng dev tên Minh - chủ một cửa hàng thương mại điện tử bán đồ gia dụng - quyết định tích hợp chatbot AI vào website của mình. Kết quả? Hệ thống chạy ngon lành với 50 khách truy cập cùng lúc, nhưng ngay khi sự kiện flash sale bắt đầu với 500 người đổ vào, API sụp đổ hoàn toàn. 5 phút downtime trong đợt sale giá chỉ còn 99K đã khiến anh thiệt hại 30 triệu đồng doanh thu. Câu chuyện này là bài học đắt giá về tầm quan trọng của việc stress test trước khi ra mắt - và hôm nay, mình sẽ hướng dẫn các bạn cách thực hiện điều đó với Locust và k6.
Tại sao phải load test API AI?
Khác với API thông thường trả về JSON trong vài mili-giây, các mô hình ngôn ngữ lớn (LLM) có đặc thù riêng:
- Thời gian phản hồi không cố định: Từ 200ms đến 30 giây tùy độ dài output
- Tài nguyên tính toán khổng lồ: GPU memory, VRAM, concurrent connections
- Chi phí theo token: Mỗi request đều tốn tiền thật - stress test lung tung có thể khiến ví bay hàng trăm đô
- Rate limiting phức tạp: Không chỉ giới hạn requests/giây mà còn tokens/phút
Với HolySheep AI, các bạn được hưởng chi phí cực kỳ cạnh tranh - chỉ từ $0.42/MTok với DeepSeek V3.2, rẻ hơn 85% so với các provider khác. Nhưng dù tiết kiệm đến đâu, việc stress test không kiểm soát vẫn có thể khiến credits bay nhanh hơn mong đợi.
Chuẩn bị môi trường
# Cài đặt Locust (Python)
pip install locust
Cài đặt k6 (macOS)
brew install k6
Hoặc download từ https://k6.io/docs/getting-started/installation/
Windows: choco install k6
# Kiểm tra cài đặt thành công
locust --version
Output: locust 2.20.0
k6 version
Output: k6 v0.48.0
Script Locust -压测 HolySheep AI
Locust là công cụ Python-based, dễ đọc và mở rộng. Mình khuyên dùng cho team có backend developer quen thuộc với Python.
# locustfile.py
import os
from locust import HttpUser, task, between, events
import json
import time
Cấu hình HolySheep AI
BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = os.getenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")
class AIAgentUser(HttpUser):
wait_time = between(1, 3) # Đợi 1-3 giây giữa các request
host = BASE_URL
def on_start(self):
"""Gọi 1 lần khi user bắt đầu"""
self.headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
# Test connection
response = self.client.get(
"/models",
headers=self.headers,
name="/models"
)
if response.status_code == 200:
print(f"[✓] Kết nối HolySheep AI thành công")
else:
print(f"[✗] Lỗi kết nối: {response.status_code}")
@task(3)
def chat_completion_short(self):
"""Task phổ biến nhất - hỏi đáp ngắn (trọng số 3)"""
payload = {
"model": "gpt-4.1",
"messages": [
{"role": "user", "content": "Liệt kê 3 cách tiết kiệm chi phí khi sử dụng AI API trong doanh nghiệp"}
],
"max_tokens": 150,
"temperature": 0.7
}
start_time = time.time()
with self.client.post(
"/chat/completions",
json=payload,
headers=self.headers,
catch_response=True,
name="/chat/completions [short]"
) as response:
latency = (time.time() - start_time) * 1000
if response.elapsed.total_seconds() > 5:
response.failure(f"Timeout! Latency: {latency:.0f}ms")
elif response.status_code == 200:
data = response.json()
usage = data.get("usage", {})
input_tokens = usage.get("prompt_tokens", 0)
output_tokens = usage.get("completion_tokens", 0)
total_cost = (input_tokens * 8 + output_tokens * 8) / 1_000_000
response.success()
print(f"[OK] {latency:.0f}ms | In:{input_tokens} Out:{output_tokens} | ~${total_cost:.6f}")
else:
response.failure(f"Lỗi HTTP {response.status_code}")
@task(1)
def chat_completion_long(self):
"""Task hiếm hơn - yêu cầu phân tích dài"""
payload = {
"model": "gpt-4.1",
"messages": [
{"role": "system", "content": "Bạn là chuyên gia phân tích thị trường E-commerce"},
{"role": "user", "content": "Phân tích chi tiết xu hướng mua sắm online tại Việt Nam 2024-2025 và đưa ra chiến lược kinh doanh cho shop nhỏ"}
],
"max_tokens": 800,
"temperature": 0.5
}
start_time = time.time()
with self.client.post(
"/chat/completions",
json=payload,
headers=self.headers,
catch_response=True,
name="/chat/completions [long]"
) as response:
latency = (time.time() - start_time) * 1000
if response.elapsed.total_seconds() > 30:
response.failure(f"Timeout nghiêm trọng! {latency:.0f}ms")
elif response.status_code == 200:
response.success()
print(f"[OK] Phân tích dài: {latency:.0f}ms")
else:
response.failure(f"Lỗi HTTP {response.status_code}")
@task(1)
def embedding_document(self):
"""Test endpoint embeddings - quan trọng cho RAG"""
payload = {
"model": "text-embedding-3-small",
"input": "Hướng dẫn sử dụng máy lọc nước Karofi 9 lõi cho gia đình 4 người"
}
with self.client.post(
"/embeddings",
json=payload,
headers=self.headers,
catch_response=True,
name="/embeddings"
) as response:
if response.status_code == 200:
response.success()
else:
response.failure(f"Embedding lỗi: {response.status_code}")
@events.test_start.add_listener
def on_test_start(environment, **kwargs):
print("🚀 Bắt đầu stress test HolySheep AI...")
print(f"📍 Target: {BASE_URL}")
print(f"💰 Rate limit: Kiểm tra response header X-RateLimit-*")
@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
print("\n📊 Kết thúc stress test!")
print("💡 Xem chi tiết tại http://localhost:8089")
# Chạy Locust với các tham số khác nhau
Test nhẹ - 10 users, spawn 2 users/giây
locust -f locustfile.py \
--headless \
--users 10 \
--spawn-rate 2 \
--run-time 60s \
--host https://api.holysheep.ai/v1
Test trung bình - 50 users
locust -f locustfile.py \
--headless \
--users 50 \
--spawn-rate 5 \
--run-time 2m \
--host https://api.holysheep.ai/v1 \
--html report.html # Xuất báo cáo HTML
Test nặng - 200 users, spawn 10 users/giây
locust -f locustfile.py \
--headless \
--users 200 \
--spawn-rate 10 \
--run-time 5m \
--host https://api.holysheep.ai/v1 \
--html report_heavy.html \
--csv results # Xuất CSV cho phân tích Excel
Chạy với Web UI (mở tab trình duyệt http://localhost:8089)
locust -f locustfile.py --host https://api.holysheep.ai/v1
Script k6 - JavaScript-based load testing
k6 được viết bằng Go, performace cao hơn Locust, phù hợp cho CI/CD pipeline và automated testing.
// load-test.js import http from 'k6/http'; import { check, sleep } from 'k6'; import { Rate, Trend } from 'k6/metrics'; // Custom metrics const errorRate = new Rate('errors'); const latencyTrend = new Trend('latency_ms'); const tokenCost = new Trend('token_cost_usd'); // Cấu hình const BASE_URL = 'https://api.holysheep.ai/v1'; const API_KEY = __ENV.HOLYSHEEP_API_KEY || 'YOUR_HOLYSHEEP_API_KEY'; // Giá token HolySheep 2026 (USD per million tokens) const TOKEN_PRICES = { 'gpt-4.1': { input: 8, output: 8 }, // $8/MTok 'claude-sonnet-4.5': { input: 15, output: 15 }, // $15/MTok 'gemini-2.5-flash': { input: 2.5, output: 2.5 }, // $2.50/MTok 'deepseek-v3.2': { input: 0.42, output: 0.42 } // $0.42/MTok }; export const options = { // Các cấu hình test phổ biến scenarios: { // Smoke test - xác nhận hệ thống hoạt động smoke: { executor: 'constant-vus', vus: 1, duration: '30s', tags: { test_type: 'smoke' } }, // Load test - mô phỏng production bình thường load: { executor: 'ramping-vus', startVUs: 0, stages: [ { duration: '1m', target: 20 }, // Tăng lên 20 users trong 1 phút { duration: '3m', target: 20 }, // Giữ 20 users trong 3 phút { duration: '1m', target: 0 } // Giảm về 0 ], tags: { test_type: 'load' } }, // Stress test - vượt ngưỡng bình thường stress: { executor: 'ramping-arrival-rate', startRate: 1, timeUnit: '1s', preAllocatedVUs: 50, stages: [ { duration: '2m', target: 5 }, // 5 requests/giây { duration: '3m', target: 15 }, // 15 requests/giây { duration: '5m', target: 30 }, // 30 requests/giây { duration: '2m', target: 0 } // Cool down ], tags: { test_type: 'stress' } }, // Spike test - đột biến đột ngột spike: { executor: 'spike', vus: 10, duration: '2m', preAllocatedVUs: 100, stages: [ { duration: '30s', target: 10 }, // Bình thường { duration: '30s', target: 100 }, // SPIKE! { duration: '2m', target: 100 }, // Giữ spike { duration: '30s', target: 10 }, // Trở về { duration: '30s', target: 0 } // Cool down ], tags: { test_type: 'spike' } } }, // Ngưỡng cho CI/CD pass/fail thresholds: { 'http_req_duration': ['p(95)<2000'], // 95% requests phải < 2s 'http_req_failed': ['rate<0.05'], // Error rate < 5% 'errors': ['rate<0.1'], // Custom error rate < 10% 'latency_ms': ['p(99)<5000'] // P99 latency < 5s } }; const headers = { 'Authorization':Bearer ${API_KEY}, 'Content-Type': 'application/json' }; export default function () { // Test với nhiều model const models = ['deepseek-v3.2', 'gemini-2.5-flash']; const model = models[Math.floor(Math.random() * models.length)]; const payload = JSON.stringify({ model: model, messages: [ { role: 'user', content: 'Tóm tắt các tính năng nổi bật của iPhone 16 Pro Max và so sánh với Samsung S24 Ultra' } ], max_tokens: 200, temperature: 0.7 }); const startTime = Date.now(); const response = http.post(${BASE_URL}/chat/completions, payload, { headers } ); const latency = Date.now() - startTime; latencyTrend.add(latency); // Parse response const success = check(response, { 'status is 200': (r) => r.status === 200, 'has content': (r) => r.json('choices') !== undefined, 'has usage': (r) => r.json('usage') !== undefined }); errorRate.add(!success); if (success) { const usage = response.json('usage'); const inputTokens = usage.prompt_tokens; const outputTokens = usage.completion_tokens; // Tính chi phí const prices = TOKEN_PRICES[model] || TOKEN_PRICES['deepseek-v3.2']; const cost = (inputTokens * prices.input + outputTokens * prices.output) / 1_000_000; tokenCost.add(cost); console.log(✅ Model: ${model} | Latency: ${latency}ms |+Tokens: ${inputTokens}+${outputTokens} | Cost: $${cost.toFixed(6)}); // Kiểm tra rate limit headers const rateLimitRemaining = response.headers['X-RateLimit-Remaining']; if (rateLimitRemaining) { console.log(⚡ Rate limit remaining: ${rateLimitRemaining}); } } else { console.error(❌ Lỗi: ${response.status} - ${response.body}); } sleep(Math.random() * 2 + 1); // Đợi 1-3 giây } // Hook để log tổng chi phí sau test export function handleSummary(data) { const totalTokenCost = data.metrics.token_cost_usd?.values?.sum || 0; return { stdout: textSummary(data), 'summary.json': JSON.stringify({ total_requests: data.metrics.http_reqs?.values?.count || 0, total_errors: data.metrics.errors?.values?.count || 0, avg_latency_ms: data.metrics.latency_ms?.values?.avg || 0, p99_latency_ms: data.metrics.latency_ms?.values['99'] || 0, total_token_cost_usd: totalTokenCost, estimated_cost_per_hour: totalTokenCost * 3600 / (data.state.testRunDurationMs / 1000) }) }; } function textSummary(data) { return ` ======================================== 📊 STRESS TEST RESULTS - HolySheep AI ======================================== Total Requests: ${data.metrics.http_reqs?.values?.count || 0} Failed Requests: ${data.metrics.http_req_failed?.values?.passes || 0} Error Rate: ${((data.metrics.errors?.values?.rate || 0) * 100).toFixed(2)}% ⏱️ Latency: - Average: ${(data.metrics.latency_ms?.values?.avg || 0).toFixed(0)}ms - P95: ${(data.metrics.latency_ms?.values['95'] || 0).toFixed(0)}ms - P99: ${(data.metrics.latency_ms?.values['99'] || 0).toFixed(0)}ms 💰 Token Cost: - Total: $${(data.metrics.token_cost_usd?.values?.sum || 0).toFixed(6)} - Est. Cost/Hour at this rate: $${((data.metrics.token_cost_usd?.values?.sum || 0) * 3600 / (data.state.testRunDurationMs / 1000)).toFixed(2)} ======================================== `; }Tài nguyên liên quan