Web サービスの開発とデプロイにおいて、負荷テストは高負荷状況下での安定性を確保するための重要なステップです。wrk
は、マルチスレッドと Lua スクリプト拡張をサポートする効率的な HTTP 負荷テストツールで、負荷テストに最適です。本記事では、実際のテスト結果を交えながら、wrk
を使用して POST リクエストの負荷テストを実施する方法と、テストデータの分析について詳しく説明します。
1. wrk
のインストール
まず、システムに wrk
をインストールします。Debian ベースのシステム(例: Ubuntu)では、以下のコマンドでインストールできます。
sudo apt update
sudo apt install wrk
インストールが完了したら、wrk --version
コマンドでインストールが成功したか確認できます。
2. POST リクエストの Body データを準備する
POST リクエストの負荷テストを行う際、通常はリクエストの Body データを指定する必要があります。Lua スクリプトを使用してこれらのデータを定義できます。例えば、./post.lua
という Lua ファイルを作成し、以下の内容を記述します。
wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json"
wrk.headers["Authorization"] = "Bearer YOUR_API_KEY" -- YOUR_API_KEY を実際の API キーに置き換える
wrk.body = [[
{
"model": "gpt-4",
"messages": [
{"role": "system", "content": "あなたはアシスタントです。"},
{"role": "user", "content": "2008年北京オリンピックで、中国は金メダルを何個獲得しましたか?"}
]
}
]]
このスクリプトでは、リクエストメソッドを POST
に設定し、Content-Type
を application/json
に指定し、リクエストの Body データを定義しています。
3. 負荷テストの実行
次に、wrk
を使用して負荷テストを実行します。サービスが http://localhost:8000/v1/chat/completions
で動作していると仮定し、以下のコマンドでテストを実施します。3 つの異なる設定でのテスト結果を記録しました。
テスト 1:シングルスレッド、シングルコネクション
まず、シングルスレッドとシングルコネクションでテストを行います。コマンドは以下の通りです。
wrk -t1 -c1 -d10s -s ./post.lua http://localhost:8000/v1/chat/completions
テスト結果:
Running 10s test @ http://localhost:8000/v1/chat/completions
1 threads and 1 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 246.58ms 274.18ms 1.43s 88.71%
Req/Sec 7.65 3.12 10.00 85.19%
54 requests in 10.00s, 30.83KB read
Requests/sec: 5.40
Transfer/sec: 3.08KB
分析:
- 平均レイテンシ(Latency)は 246.58ms、最大レイテンシは 1.43s。
- 1 秒あたりのリクエスト数(Requests/sec)は 5.40。
- 合計 54 リクエストが完了。
テスト 2:シングルスレッド、10 コネクション
次に、コネクション数を 10 に増やしてテストを行います。コマンドは以下の通りです。
wrk -t1 -c10 -d10s -s ./resources/2_9/post.lua http://localhost:8000/v1/chat/completions
テスト結果:
Running 10s test @ http://localhost:8000/v1/chat/completions
1 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 259.59ms 146.24ms 1.09s 85.20%
Req/Sec 40.76 13.56 80.00 75.00%
397 requests in 10.01s, 229.39KB read
Requests/sec: 39.66
Transfer/sec: 22.92KB
分析:
- 平均レイテンシは 259.59ms、最大レイテンシは 1.09s。
- 1 秒あたりのリクエスト数は 39.66。
- 合計 397 リクエストが完了。
テスト 3:シングルスレッド、20 コネクション
最後に、コネクション数を 20 に増やしてテストを行います。コマンドは以下の通りです。
wrk -t1 -c20 -d10s -s ./resources/2_9/post.lua http://localhost:8000/v1/chat/completions
テスト結果:
Running 10s test @ http://localhost:8000/v1/chat/completions
1 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 314.60ms 164.85ms 1.74s 83.87%
Req/Sec 59.45 17.00 100.00 64.58%
582 requests in 10.01s, 332.09KB read
Socket errors: connect 0, read 0, write 0, timeout 2
Requests/sec: 58.15
Transfer/sec: 33.18KB
分析:
- 平均レイテンシは 314.60ms、最大レイテンシは 1.74s。
- 1 秒あたりのリクエスト数は 58.15。
- 合計 582 リクエストが完了しましたが、2 リクエストがタイムアウトしました。
4. テスト結果のまとめ
上記の 3 つのテストから、以下の結論が得られます。
-
レイテンシの分析:
- コネクション数が増えるにつれ、平均レイテンシと最大レイテンシが上昇します。例えば、シングルコネクション時の平均レイテンシは 246.58ms でしたが、20 コネクション時には 314.60ms に増加しました。
- これは、サービスがより多くの同時リクエストを処理する際に、応答時間が長くなることを示しています。
-
スループットの分析:
- 1 秒あたりのリクエスト数は、コネクション数が増えるにつれて大幅に向上します。シングルコネクション時は 5.40、10 コネクション時は 39.66、20 コネクション時は 58.15 でした。
- これは、サービスがより多くの同時リクエストを処理できることを示していますが、レイテンシの増加とのトレードオフが必要です。
-
エラーの分析:
- 20 コネクションのテストでは、2 つのタイムアウトエラーが発生しました。これは、高負荷状況下でサービスの処理能力が限界に達した可能性を示しています。
5. 最適化の提案
テスト結果に基づき、以下の最適化対策を検討できます。
- サービスインスタンスの増加:ロードバランサーを使用して複数のサービスインスタンスにリクエストを分散させ、負荷を分担します。
- コードロジックの最適化:キャッシュや非同期処理などを通じて、リクエスト処理時間を短縮します。
- サーバー設定の調整:CPU やメモリなどのリソースを増強し、サービスの処理能力を向上させます。
6. まとめ
以下は、3 回のテスト結果をまとめた表です。比較と分析に役立ちます。
設定 | スレッド数 (-t ) |
コネクション数 (-c ) |
平均レイテンシ (Avg Latency) | 最大レイテンシ (Max Latency) | 1 秒あたりのリクエスト数 (Requests/sec) | 総リクエスト数 | 総転送データ | 転送速度 (Transfer/sec) | エラー数 |
---|---|---|---|---|---|---|---|---|---|
wrk -t1 -c1 |
1 | 1 | 246.58ms | 1.43s | 5.40 | 54 | 30.83KB | 3.08KB | 0 |
wrk -t1 -c10 |
1 | 10 | 259.59ms | 1.09s | 39.66 | 397 | 229.39KB | 22.92KB | 0 |
wrk -t1 -c20 |
1 | 20 | 314.60ms | 1.74s | 58.15 | 582 | 332.09KB | 33.18KB | 2 (timeout) |
表の分析
-
レイテンシ:
- コネクション数が増えるにつれ、平均レイテンシと最大レイテンシが徐々に上昇します。
- シングルコネクション時、平均レイテンシは 246.58ms。
- 10 コネクション時、平均レイテンシは 259.59ms。
- 20 コネクション時、平均レイテンシは 314.60ms。
- これは、サービスがより多くの同時リクエストを処理する際に、応答時間が長くなることを示しています。
- コネクション数が増えるにつれ、平均レイテンシと最大レイテンシが徐々に上昇します。
-
スループット:
- 1 秒あたりのリクエスト数(Requests/sec)は、コネクション数が増えるにつれて大幅に向上します。
- シングルコネクション時、1 秒あたり 5.40 リクエスト。
- 10 コネクション時、1 秒あたり 39.66 リクエスト。
- 20 コネクション時、1 秒あたり 58.15 リクエスト。
- これは、サービスがより多くの同時リクエストを処理できることを示していますが、レイテンシの増加とのトレードオフが必要です。
- 1 秒あたりのリクエスト数(Requests/sec)は、コネクション数が増えるにつれて大幅に向上します。
-
エラー数:
- 20 コネクションのテストでは、2 つのタイムアウトエラーが発生しました。これは、高負荷状況下でサービスの処理能力が限界に達した可能性を示しています。
-
転送データ:
- リクエスト数が増えるにつれ、総転送データと転送速度も向上します。
- シングルコネクション時、転送速度は 3.08KB/s。
- 10 コネクション時、転送速度は 22.92KB/s。
- 20 コネクション時、転送速度は 33.18KB/s。
- リクエスト数が増えるにつれ、総転送データと転送速度も向上します。
表から明らかなように:
- コネクション数を増やすことで、サービスのスループットが大幅に向上しますが、レイテンシも増加します。
- 高負荷状況下(例: 20 コネクション)では、タイムアウトエラーが発生する可能性があり、サービスがさらなる最適化を必要とすることを示しています。
この表形式の表示は、テストレポートや性能分析ドキュメントに非常に適しており、異なる設定下での性能を直感的に比較できます。
本記事では、wrk
を使用して POST リクエストの負荷テストを実施し、コネクション数を増やすことで異なる同時接続シナリオをシミュレートする方法を紹介しました。テスト結果から、サービスが高負荷状況下でレイテンシが増加する一方で、スループットが大幅に向上することがわかりました。適切な最適化対策を講じることで、サービスの性能と安定性をさらに向上させることができます。
参考リンク: