load-testing について
k6、Artillery、Locustの例やテスト種別、計画・確認の指針をまとめた負荷テストスキルです。開発者が通常時や高負荷時のアプリケーションの挙動を評価する際に役立ちます。
主な機能
- 01k6、Artillery、Locustの例
- 02認証リクエストのパターン
- 03スモーク、負荷、ストレス、ソーク、スパイクテスト
- 04しきい値と現実的なシナリオの指針
活用シーン
- 01APIの負荷テスト作成
- 02性能目標に応じたテスト種別の選択
- 03負荷テスト計画にある一般的な問題の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill load-testingインストール後、Claude Code で/load-testingを入力して読み込まれたか確認します。
詳細
負荷テスト
k6(推奨)
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '1m', target: 50 }, // Ramp up to 50 users
{ duration: '3m', target: 50 }, // Stay at 50
{ duration: '1m', target: 100 }, // Ramp to 100
{ duration: '3m', target: 100 }, // Stay at 100
{ duration: '1m', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<500', 'p(99)<1000'], // 95th < 500ms
http_req_failed: ['rate<0.01'], // <1% error rate
},
};
export default function () {
const res = http.get('https://api.example.com/products');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
認証済みリクエスト
import http from 'k6/http';
export function setup() {
const res = http.post('https://api.example.com/auth/login', JSON.stringify({
email: '[email protected]', password: 'test-password',
}), { headers: { 'Content-Type': 'application/json' } });
return { token: res.json('token') };
}
export default function (data) {
const headers = { Authorization: `Bearer ${data.token}`, 'Content-Type': 'application/json' };
// Simulate user journey
http.get('https://api.example.com/products', { headers });
sleep(2);
http.get('https://api.example.com/products/1', { headers });
sleep(1);
http.post('https://api.example.com/orders', JSON.stringify({ productId: '1', qty: 2 }), { headers });
}
Artillery
# artillery.yml
config:
target: "https://api.example.com"
phases:
- duration: 60
arrivalRate: 10
name: "Warm up"
- duration: 120
arrivalRate: 50
name: "Sustained load"
defaults:
headers:
Content-Type: "application/json"
scenarios:
- name: "Browse and purchase"
flow:
- get:
url: "/products"
capture:
- json: "$.data[0].id"
as: "productId"
- think: 2
- get:
url: "/products/{{ productId }}"
- think: 1
- post:
url: "/orders"
json:
productId: "{{ productId }}"
quantity: 1
Locust(Python)
from locust import HttpUser, task, between
class WebUser(HttpUser):
wait_time = between(1, 3)
def on_start(self):
res = self.client.post("/auth/login", json={
"email": "[email protected]", "password": "password"
})
self.token = res.json()["token"]
self.headers = {"Authorization": f"Bearer {self.token}"}
@task(3)
def browse_products(self):
self.client.get("/products", headers=self.headers)
@task(1)
def create_order(self):
self.client.post("/orders", json={"productId": "1", "qty": 1}, headers=self.headers)
テストの種類
| 種類 | 目的 | 期間 |
|---|---|---|
| スモーク | 最小限の負荷でシステムが動作することを確認します | 1-2 分 |
| 負荷 | 想定される通常時/ピーク時のトラフィックを再現します | 10-30 分 |
| ストレス | 通常の処理能力を超える負荷をかけ、限界点を特定します | 10-20 分 |
| ソーク | 継続的な負荷をかけ、メモリリークを特定します | 1-4 時間 |
| スパイク | 突発的なトラフィックの急増を再現します | 5-10 分 |
アンチパターン
| アンチパターン | 対策 |
|---|---|
| サーバーと同じネットワークからテストする | 外部ネットワークまたはクラウドからテストします |
| リクエスト間に思考時間を設けない | 現実的な sleep/think の遅延を追加します |
| 単一のエンドポイントのみをテストする | 現実的なユーザージャーニーをテストします |
| しきい値を定義しない | p95/p99 のレイテンシとエラー率のしきい値を設定します |
| 本番環境に対して負荷テストを実行する | ステージング環境を使用します |
本番環境向けチェックリスト
- 現実的なユーザーシナリオ(単一のエンドポイントだけではない)
- レイテンシ(p95、p99)とエラー率のしきい値
- 想定されるトラフィックの形状に合ったランプアップパターン
- テストデータを事前に投入する(同じレコードを再利用しない)
- リグレッション検出のための CI/CD 統合
- 経時比較のために結果をアーカイブする
コメント
Markdown 対応