負荷試験#リクエストの分類

久々に負荷試験についての続編です。

様々な処理をチェックしていく上で、どのようなリクエストがあるのかってのを意識しておくと進めやすくなると思うのです。



少しずつ進める

さぁ負荷試験をやりましょうってなった時、クライアントツールを用意して、アプリケーションコードとテストデータ、サーバーリソースを準備したら、ようやく大量のトラフィックを発生させましょうとなります。それにはシナリオが必要で、どのようなリクエストを投げるかを表したコードやデータを作成することになります。

このシナリオをどのように作るかは、目的や人によって異なるのですが、まずはじめに示しておきたいこととしては、一気に全部作ろうとしないで、少しずつ作りながら実行した方がよいということです。

負荷試験は何をどこまでやるのか、を考える必要があるし、実行してから何度も調整することが多くあります。そのため、最初から全部の処理を網羅して、割合を調整して、エラーも出ないように、なんてやろうとすると、おそらく無駄が生じまくって時間が勿体ないです。

アプリケーションによって構成や複雑さはマチマチなので、ザックリ全体像を掴み、どのようなリクエストがあるのか分類し、分類ごとに負荷試験して精査していくとよいです。そして最終段階として、それらの結果を合算した上で、最終確認の意味で全体としての試験をするのが、精度を考えると結果的に近道になるのではないでしょうか。

ということで、ここではリクエストにはどのような分類があるのか、について整理していきます。


リクエストの基本形分別

ではまず、リクエストを基本形で分別してみます。様々な分類がある中で、複数の性質を混ぜた試験にしてしまうと、本質的な品質や原因が見えづらくなるため小分けにすることは有効です。

世の中、色んなサービスがありますし、プロトコルを複数活用する場合もありますので、とりあえずこれが最小例ということで。

Read:ユーザー単体での参照系アクセス

主に HOME や データリストなど、何度でもアクセス可能な処理のことです。

Read(参照系)と言ってもHOME画面などでは、なにかしらのデータ更新を発生させていても不思議ではありませんが、負荷試験としては無条件で何度でもアクセスを繰り返せる、ところがポイントとなります。

シナリオとしては、単純にリクエスト内容を作成するだけでよく、何度もループアクセスすることができるので、素早く試験に取り掛かることができる分類となります。

そういう意味では参照だけではなく、一部の更新系の処理も含むことができます。例えばメッセージの送信などの蓄積系や、名前変更でのデータ上書きなどは、何度も実行することが可能な場合があります。

このような早い取り組みができる分類は、とりあえずサクッとやってみるのが重要で、根本となるシナリオやユーザーセッションの動作確認を確かのものにし、このサービス環境における平均レスポンス速度など基準的な情報を知ることができます。

それができてから小難しいことを肉付けしていけばよく、一気にやろうとしてイッパイ問題をかかえるよりも、土台あれば憂いなしです。

Write:ユーザー単体での更新系アクセス

例えばプレゼントの受け取りや、アイテムの消費といったアクションは、2回め以降に同じリクエストをしてもエラーになることが多いです。これは消費済みになってしまうからで、エラーステータスコードが返っちゃうし、かかる負荷としては正しくなくなってしまうので、対応する必要があります。

1つはテストデータとシナリオを調整することで、開始から終了までエラーにならない構成にすることが考えられますが、それだとリクエスト数が確定してしまうので時間幅や Req/s の調整が難しくなることや、再実行の際にテストデータの巻き戻しが必要になります。それでは、構成の難しさに対して、あまり効率的とは言えません。

なので変更処理ごとに、エラーにならないよう直前にデータ調整を仕込む方が無難です。何度ループしても成功するので扱いやすいですが、余分な処理量が増えることも事実なので、負荷としては微増すると認識する必要はあります。逆に言うと、本番の方が若干軽くなるわけで、それが反対になるよりはマシとも言えます。

こういった調整必須な処理は、アプリケーションには多く存在し、サクッと作ったシナリオを軽く回すだけでも、エラーコードが返ることですぐ存在に気づくことができます。

この調整対応はそれなりに時間がかかるので、どのくらい存在し、どこまで対応すべきなのか、というのは結構肝になります。場合によっては完全に網羅する必要もあるでしょうが、『動作確認』ではなくあくまで『負荷試験』であるならば一部省略する判断をもって、後述するリクエストごとの重要度を考慮することになります。

Multi:マルチユーザーでのアクセス

これは特にHTTP以外のプロトコルも用いる可能性が高いものですが、マルチユーザーで何かをするということは、共通のグループや部屋といったものを作成・接続し、相互に(多くはサーバーを通じて)通信を行います。

そのため、負荷試験時には複数のユーザーを、複数の部屋と結びつけるような M:N のマッチング処理が必要になり、アプリケーションでの運用作業が伴う試験となります。

そしてマルチプレイがあるサービスは、マルチの重要度が高いことが多く、ユーザーの評価に強く直結するため、より入念なテストが必要です。

Event:時限式のアクセス

これも運用作業が伴う試験で、特定の時間帯や期間にしか処理できない、イベント形式のアクセスがあります。

シナリオはあっても設定時間外だとエラーになるので、試験する時に有効にしてもらうか、長い時間だしっぱなしにしてもらう必要があります。

開始時や終了時など、特にアクセスが集中しやすい箇所なので、そのトラフィック落差に適切な対応をするための、より精度の高い調査が求められます。


リクエストの重量分別

さきほどまでは、シナリオや試験の進み方に関わる分別でしたが、こちらは試験結果の分別メインです。NewRelic みたいな外部サービスを仕込むと、集計してくれるので簡単ですが、負荷試験ツールでも十分なモノもあります。

リクエストを重さ・影響度といった分別にします。サーバーを重くする処理には大雑把に2種類あり、1つは1回あたりの処理が遅いもの、もう1つはアクセス割合が高いものです。

処理時間

処理によっては、そもそも常に重かったり、ヘビーユーザーなど特定のデータ条件などで重くなるものがあります。大半は平均速度に近い処理になりますが、中には異常と判断できる突出した処理時間をかける処理があるので、それを炙り出すことが負荷試験の目的の1つといえます。

”重い” とはどういう状態か、というのは明確に定義しておくべきです。例えば、HTTPならば全て1.0秒以下を理想とし、それ以上はチューニングの対象、3秒以上はユーザー離れの原因と捉える。というような指標です。マルチ用のプロトコルやリアルタイム性の強い処理ならば、より小さい数値を求められるでしょう。

悪い方向に条件を満たした処理は、悪い数値順に優先順とし、解決していく対象とします。これらは、1つ解決するだけで大きな一歩となるお宝でもあります。

アクセス割合

1つ1つは軽量でも、アクセス頻度が高い処理は合計すると消費リソースとしては大きくなります。リソース不足にならない限りは、レスポンス速度は正常範囲なので、放っておくのもひとつの手ですが…… 消費リソース割合が高いということは、改善により全体のリソースを減らすチャンス。また、アクセス割合が高いということは、改善により多くのユーザーの体感を改善できるチャンスでもあります。

例えば全体の20%を占める処理は、全体の10%を占める処理よりも優先的に改善すべきということです。逆に、割合が極小な処理は、ある程度は精査をスルーすることも選択肢としてありえます。

この割合は、既存サービスならば何かしらのアクセスログの集計があれば、簡単に確認することができます。新規サービスの場合、仕様を把握する者がそれらしい割合を想定するか、テストユーザーとして振る舞いアクセスした上で集計することで、それなりに本番らしい割合を作ることができます。

処理の合計時間

この2つを合わせたものが処理の合計時間で、ある期間におけるサーバーへの影響度と考えることができます。

例えば1分間の間に、1回に0.1秒かかる処理(A)が100回と、1回に0.5秒かかる処理(B)が10回だとすると、各合計は (A)10秒 (B)5秒 となり、(A)の方が影響度が高いことがわかります。

もし、各処理を10%ずつ改善したとしたら、(A)の方が改善度が高くなるので、優先度としては(A)が高いことになります。

ただこれは、あくまで机上の話であって、実際には (A)0.1秒を10%改善するよりも、(B)0.5秒を10%改善する方が、総合的なユーザー体感に好影響となるかもしれませんし、(A)よりも(B)の方が改善の余地が残されている可能性が高いとも考えられます。

ある程度、負荷試験として形になってきた時に、こういった重さによる影響度ランキングを整理するわけですが、絶対上位から解決していけという意味ではなく、上位10位までで改善しやすいところから取り掛かっていこう。くらいの話になります。


続く

こういう感じに、分類と優先順位を丁寧に整理しつつ、負荷試験を実行しつつ、アプリケーションの性質を理解していきます。

それを理解した上で、ではどう進めていくかというと、まずはその負荷試験が何を目的として行うべきか、について考える必要があります。

が、長くなるので、進め方・考え方については
⇦To Be Continued…