アプリケーション ロードバランサを使用したバックエンド サービスの負荷テストに関するガイドライン

バックエンド サービスをアプリケーション ロードバランサと統合する場合は、ロードバランサを使用せずに、バックエンド サービスのパフォーマンスを単独で測定することが重要です。制御された条件下での負荷テストを行うことにより、スループットやレイテンシなど、さまざまなディメンションのパフォーマンスを比較し、キャパシティ プランニングのトレードオフを評価できます。キャパシティ プランニングを慎重に行っても、実際の需要を過小評価する可能性があります。そのため、負荷テストを実施して、システムが過負荷状態のときにサービスの可用性がどのような影響を受けるのかを事前に確認することをおすすめします。

負荷テストの目標

一般的な負荷テストでは、さまざまなディメンションの負荷をかけて、外部から見えるバックエンド サービスの動作を測定します。このテストで最も関連性の高いディメンションは次のとおりです。

  • リクエストのスループット: 1 秒あたりに処理されるリクエストの数。
  • リクエストの同時実行: 同時に処理されたリクエストの数。
  • 接続スループット: クライアントが 1 秒あたりに開始した接続の数。Transport Layer Security(TLS)を使用するほとんどのサービスでは、リクエストの処理に関係なく、それぞれの接続に関連付けられたネットワーク トランスポートと TLS ネゴシエーションでオーバーヘッドが発生します。
  • 接続の同時実行: 同時に処理されたクライアント接続の数。

  • リクエストのレイテンシ: リクエストの開始からレスポンスの終了までにかかった合計時間。

  • エラー率: リクエストが、HTTP 5xx エラーや接続の早期切断などのエラーを発生させる頻度。

負荷テストでは、負荷がかかったサーバーの正常性を評価するため、次の内部サービスの指標を収集することがあります。

  • システム リソースの使用: 通常、CPU、RAM、ファイル ハンドル(ソケット)などのシステム リソースの使用率はパーセントで示されます。

    これらの指標の重要性は、サービスの実装方法によって異なります。アプリケーションのリソースが枯渇すると、アプリケーションのパフォーマンスが低下し、負荷がかかり、クラッシュにつながる可能性があります。そのため、ホストに高い負荷がかかっているときは、リソースの可用性を判断することが重要になります。

  • 他の制限付きリソースの使用: アプリケーション レイヤなど、過負荷状態になる可能性があるシステム以外のリソース。

    このようなリソースとしては、次のものがあります。

    • ワーカー スレッドまたはプロセスの制限付きプール。
    • スレッドを使用するアプリケーション サーバーでは、同時に動作するワーカー スレッドの数を制限するのが一般的です。スレッドプール サイズの上限は、メモリと CPU の枯渇を防ぐために役立ちますが、デフォルト設定はかなり控えめになっていることが少なくありません。上限が低すぎると、システム リソースを適切に使用できなくなる可能性があります。
    • 一部のサーバーでは、スレッドプールではなくプロセスプールが使用されています。たとえば、Apache サーバーが Prefork Multi-Processing Model で設定されている場合、クライアント接続ごとに 1 つのプロセスが割り当てられます。したがって、プールのサイズ上限により、接続の同時実行の上限が決まります。
    • 制限付きサイズのバックエンド接続プールを持つ別のサービスにフロントエンドとしてデプロイされたサービス。

キャパシティ プランニングと過負荷テスト

負荷テストツールを使用すると、さまざまなスケーリング ディメンションを個別に測定できます。キャパシティ プランニングでは、複数のディメンションで許容可能なパフォーマンスの負荷しきい値を決定します。たとえば、全体的なサービス リクエストの絶対的な上限ではなく、以下を測定することを検討してください。

  • サービスが、指定のミリ秒を下回る 99 パーセンタイルのレイテンシでサービスを提供できるリクエスト レートこの値は、サービスの SLO によって指定されます。
  • システム リソース使用率が最適レベルを超えることのない最大リクエスト レート。最適な使用率はアプリケーションによって異なり、100% を大幅に下回ることもあります。たとえば、ピーク時のメモリ使用率が 80% の場合、ピーク使用率が 99% の場合よりも、アプリケーションが小規模な負荷の急増を適切に処理できることがあります。

負荷テストの結果を使用してキャパシティ プランニングを行うことは重要ですが、負荷が容量を超過した場合のサービスの動作についても把握しておく必要があります。過負荷テストで評価されることが多いサーバーの動作は次のとおりです。

  • 負荷制限: サービスは、過剰な受信リクエストや接続を受信したときに、すべてのリクエストを遅らせるか、一部のリクエストを拒否して、残りのリクエストのパフォーマンスを許容範囲で維持することで対応します。後者の方法を採用して、レスポンスを受信する前にクライアントのタイムアウトを防ぎ、サーバーに対するリクエストの同時実行数を減らすことでメモリ不足のリスクを回避することをおすすめします。

  • リソースの枯渇に対する復元力: 通常、サービスがクラッシュした場合、保留中のリクエストを続行することは難しいため、サービスはリソースの枯渇によるクラッシュを回避します。バックエンド サービスに多くのインスタンスがある場合は、サービス全体の可用性を高めるため、個々のインスタンスの堅牢性が重要となります。インスタンスがクラッシュから再起動している間は、他のインスタンスの負荷が増加し、カスケード障害が発生する可能性があります。

一般的なテストのガイドライン

テストケースを定義する際は、次のガイドラインを考慮してください。

小規模なテストを作成する

小規模なテストを作成して、サーバーのパフォーマンス制限を測定します。サーバーの容量が多すぎると、テストでサービス自体のパフォーマンス上限が明らかにならない可能性がありますが、クライアント ホストやネットワーク レイヤなど、他のシステムのボトルネックが見つかる可能性もあります。

最適な結果を得るため、1 つの仮想マシン(VM)インスタンスまたは Google Kubernetes Engine(GKE)Pod を使用して、サービスを個別にテストするテストケースを作成することを検討してください。サーバーを完全に読み込むと、必要に応じて複数の VM が使用されますが、パフォーマンス データの収集は複雑になる場合があります。

オープンループの負荷パターンを選択する

ほとんどの負荷生成ツールは、クローズドループ パターンを使用して同時リクエストの数を制限し、前のリクエストが完了するまで新しいリクエストを遅らせます。サービスの本番環境のクライアントでは、このようなスロットリング動作が行われない可能性があるため、この方法はおすすめしません。

一方、オープンループ パターンの場合、サーバーのレスポンスが到達するレートに関係なく、一定のレートでリクエストを送信して本番環境の負荷をシミュレートできます。

バックエンド サービスの負荷テストには、次の負荷生成ツールを使用することをおすすめします。

Nighthawk

Nighthawk は Envoy プロジェクトと連携して開発されたオープンソース ツールです。クライアントの負荷の生成やベンチマークの可視化に使用できます。また、HTTPS サービスのほとんどの負荷テストシナリオでサーバー パフォーマンスを測定できます。

HTTP/1 をテストする

HTTP/1 をテストするには、次のコマンドを使用します。

nighthawk_client URI \
    --duration DURATION \
    --open-loop \
    --no-default-failure-predicates \
    --protocol http1 \
    --request-body-size REQ_BODY_SIZE \
    --concurrency CONCURRENCY \
    --rps RPS \
    --connections CONNECTIONS

次のように置き換えます。

  • URI: ベンチマークを行う URI
  • DURATION: 合計テスト実行時間(秒)
  • REQ_BODY_SIZE: 各リクエスト内の POST ペイロードのサイズ
  • CONCURRENCY: 同時イベントループの合計数

    この数値は、クライアント VM のコア数と一致する必要があります

  • RPS: イベントループごとの 1 秒あたりのリクエストのターゲット レート

  • CONNECTIONS: イベントループあたりの同時接続数

次の例をご覧ください。

nighthawk_client http://10.20.30.40:80 \
    --duration 600 --open-loop --no-default-failure-predicates \
    --protocol http1 --request-body-size 5000 \
    --concurrency 16 --rps 500 --connections 200

各テスト実行の出力は、レスポンスのレイテンシのヒストグラムを提供します。Nighthawk のドキュメントの例では、99 パーセンタイルのレイテンシは約 135 マイクロ秒であるので注意してください。

Initiation to completion
    samples: 9992
    mean:    0s 000ms 113us
    pstdev:  0s 000ms 061us

    Percentile  Count       Latency
    0           1           0s 000ms 077us
    0.5         4996        0s 000ms 115us
    0.75        7495        0s 000ms 118us
    0.8         7998        0s 000ms 118us
    0.9         8993        0s 000ms 121us
    0.95        9493        0s 000ms 124us
    0.990625    9899        0s 000ms 135us
    0.999023    9983        0s 000ms 588us
    1           9992        0s 004ms 090us

HTTP/2 をテストする

HTTP/2 をテストするには、次のコマンドを使用します。

nighthawk_client URI \
    --duration DURATION \
    --open-loop \
    --no-default-failure-predicates \
    --protocol http2 \
    --request-body-size REQ_BODY_SIZE \
    --concurrency CONCURRENCY \
    --rps RPS \
    --max-active-requests MAX_ACTIVE_REQUESTS \
    --max-concurrent-streams MAX_CONCURRENT_STREAMS

次のように置き換えます。

  • URI: ベンチマークを行う URI
  • DURATION: 合計テスト実行時間(秒)
  • REQ_BODY_SIZE: 各リクエスト内の POST ペイロードのサイズ
  • CONCURRENCY: 同時イベントループの合計数

    この数値は、クライアント VM のコア数と一致する必要があります

  • RPS: 各イベントループの 1 秒あたりのリクエストのターゲット レート。

  • MAX_ACTIVE_REQUESTS: 各イベントループに対する同時アクティブ リクエストの最大数

  • MAX_CONCURRENT_STREAMS: 各 HTTP/2 接続で許可される同時ストリームの最大数

次の例をご覧ください。

nighthawk_client http://10.20.30.40:80 \
    --duration 600 --open-loop --no-default-failure-predicates \
    --protocol http2 --request-body-size 5000 \
    --concurrency 16 --rps 500 \
    --max-active-requests 200 --max-concurrent-streams 1

ab(Apache ベンチマーク ツール)

ab は、Nighthawk ほどの柔軟性はありませんが、ほぼすべての Linux ディストリビューションのパッケージとして使用できます。ab は、すばやく簡単にテストを行う場合にのみ使用することをおすすめします。

ab をインストールするには、次のコマンドを使用します。

  • Debian と Ubuntu の場合は、sudo apt-get install apache2-utils を実行します。
  • RedHat ベースのディストリビューションの場合は、sudo yum install httpd-utils を実行します。

ab をインストールしたら、次のコマンドを使用して実行します。

ab -c CONCURRENCY \
    -n NUM_REQUESTS \
    -t TIMELIMIT \
    -p POST_FILE URI

次のように置き換えます。

  • CONCURRENCY: 実行する同時リクエストの数
  • NUM_REQUESTS: 実行するリクエストの数。
  • TIMELIMIT: リクエストの最大時間(秒)
  • POST_FILE: HTTP POST ペイロードを含むローカル ファイル
  • URI: ベンチマークを行う URI

次の例をご覧ください。

ab -c 200 -n 1000000 -t 600 -P body http://10.20.30.40:80

上記の例のコマンドは、200(クローズド ループ パターン)の同時実行数でリクエストを送信し、1,000,000(100 万)リクエストまたは 600 秒後に停止します。このコマンドには、ファイル body の内容も HTTP POST ペイロードとして含まれます。

ab コマンドは、Nighthawk と同様のレスポンス レイテンシのヒストグラムを生成しますが、その解像度はマイクロ秒ではなくミリ秒です。

Percentage of the requests served within a certain time (ms)
    50%     7
    66%     7
    75%     7
    80%     7
    90%    92
    95%   121
    98%   123
    99%   127
    100%  156 (longest request)

次のステップ