こんにちは。よっしーです(^^)
今日は、APIの負荷テストについてご紹介します。
背景
Dockerで構築したWebアプリの開発環境において、k6を利用した負荷テストについて調査したときの内容を備忘として残しました。
開発環境のソースは下記のリポジトリにあります。
ワークロードの設定
ワークロードを設定するには、テストオプションを使用します。テスト負荷はテストによって生成されるトラフィックを設定します。k6では、負荷をモデル化するための2つの主要な方法が提供されています:
- 仮想ユーザー(Virtual Users、VUs)を介して、同時ユーザーをシミュレートします。
- 秒間リクエスト数を介して、生の実世界のスループットをシミュレートします。
注意: 通常、負荷テストにはスリープ時間を追加する必要があります。スリープ時間は負荷ジェネレーターを制御し、人間のユーザーのトラフィックパターンをより適切にシミュレートするのに役立ちます。
ただし、API負荷テストに関しては、スリープに関するこれらの推奨事項にはいくつかの制限があります。孤立したコンポーネントをテストする場合、通常のスループットの下でのパフォーマンスのみを考慮するかもしれません。しかし、この場合でも、スリープは負荷ジェネレーターを過度に稼働させないために役立ち、数ミリ秒のランダムなスリープを含めることで偶発的な並行性を回避できます。
通常の、人間によって実行されるワークフローに対してAPIをテストする場合は、通常のテストと同様にスリープを追加します。
仮想ユーザー
VUsに基づいて負荷をモデル化する場合、基本的な負荷オプションは次のとおりです:
- vus
- duration
- iterations
これらのオプションをテストスクリプトで定義できます。以下のテストでは、50の同時ユーザーが30秒間、デフォルトのフローを継続的に実行します。
import http from 'k6/http';
export const options = {
vus: 50,
duration: '30s',
};
export default function () {
const payload = JSON.stringify({
name: 'lorem',
surname: 'ipsum',
});
const headers = { 'Content-Type': 'application/json' };
http.post('https://httpbin.test.k6.io/post', payload, { headers });
}
リクエストレート
APIエンドポイントのパフォーマンスを分析する際、負荷は通常、リクエストレート(秒あたりまたは分あたりのリクエスト数)で報告されます。
目標リクエストレートに従ってワークロードを設定する場合、constant-arrival-rate executorを使用します。
constant-arrival-rateは、スクリプト関数を実行するイテレーションの一定のレートを設定します。各イテレーションは1つまたは複数のリクエストを生成できます。
リクエストレートの目標(RequestsRate)に到達するためには、次の手順を実行します:
- 目標の時間単位に合わせてレートの頻度を設定します。秒ごとまたは分ごとです。
- イテレーションごとのリクエスト数(RequestsPerIteration)を取得します。
- イテレーションレートを、リクエストレートの目標をイテレーションごとのリクエスト数で割った値に設定します。 rate = RequestsRate ÷ RequestsPerIteration
前述の例で50リクエスト/秒の目標に到達するには、次のようにします:
- timeUnitオプションを1秒に設定します。
- イテレーションごとのリクエスト数は1です。
- rateオプションを50/1(つまり50)に設定します。
import http from 'k6/http';
export const options = {
scenarios: {
my_scenario1: {
executor: 'constant-arrival-rate',
duration: '30s', // total duration
preAllocatedVUs: 50, // to allocate runtime resources preAll
rate: 50, // number of constant iterations given `timeUnit`
timeUnit: '1s',
},
},
};
export default function () {
const payload = JSON.stringify({
name: 'lorem',
surname: 'ipsum',
});
const headers = { 'Content-Type': 'application/json' };
http.post('https://httpbin.test.k6.io/post', payload, { headers });
}
このテストは、http_reqsメトリック上のHTTPリクエストの総数とRPS(Requests Per Second、秒間リクエスト数)を出力します。
# the reported value is close to the 50 RPS target
http_reqs......................: 1501 49.84156/s
# the iteration rate is the same as rps, because each iteration runs only one request
iterations.....................: 1501 49.84156/s
おわりに
今日は、APIの負荷テストについてご紹介しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント