負荷試験シリーズ、今回は実行時の条件と結果の読み取りについて考えていきます。
どのようなな調整で負荷試験を進めていけば、より効率的に正確な成果を得られるのか。これはただのパワーゲームではありません。
誤った考え方
アプリケーションが多様ゆえに、負荷試験にも完全な正解はないかもしれませんが、限りなく正着といえる手法はあります。負荷試験を始めましょう、となった時にヤラカシがちなのが、いきなり本番想定のサーバー量で試験を始めることです。このサービスの想定DAUがいくらで、ピークタイムのRPSがいくらになりそうだから、サーバーはこのくらいだろう。と用意してそれに負荷をかけ、大丈夫だの足りないだのやりだすことの、なんと意味の薄いことか。
もしそれがオンプレミスならありえます。なぜなら、サービスが完成するだいぶ前には物理サーバーの準備ができている必要があり、そこから増減を考える意味がないからです。今その環境でできる最大条件でのみ試験してもおかしくはありません。
本番想定のみで調整してOK出しても、いざ本番投入で上手くいかなければそりゃそーだ。上手くいっても今回は運が良かったね。という程度の試験品質に過ぎません。
では、なぜ本番のみを想定した試験がイケてないのか、というよりはどうするべきなのか、を追っていきます。
点ではなく線で捉える
現代はクラウドが基本なので、スケールアップやスケールアウトが容易であるアドバンテージを活かした試験計画にしていきます。仮にサーバー1台での試験でも、条件に対する考え方は同じです。本番想定の結果のみ、という成果は『点』でしかありません。リソース量を倍にしたり半分にしたらどう変化するだろうという予測に信憑性がなかったり、点において発生して解決した問題が、下位のどの条件あたりで発生するものなのか不明なままになる、といった不十分な結果と言えます。
16vCPUs のインスタンスで 1000 RPS 捌けると計測したとしても、倍や半分のリソースにした時にほぼ比例するかはわかりません。
運用には想定するトラフィック量があるとして、その動作保証は必須となりますが、そのトラフィックがさらに2~3倍になったらどうなるのか、どう対処するのか。逆に減少したときは、どのように縮退するのか。も同様に重要です。
なぜなら、想定通りにならないことは少なくないし、同じ傾向の流量で動き続けることもないからです。なので、想定ただ1点の試験結果に高い価値がないということは間違いありません。
正着としては複数の条件下で結果を採取します。現実的な範囲における最小の条件で採取し、そこから倍々もしくは同値加算ずつ増やした結果をいくつか採取します。
例えば 2vCPUs から 4, 8 と試験して結果を見れば、続きの 16, 32 でのRPSを推測することができます。
X軸に2点あればY軸の増加率を算出でき、3点目以降でその信憑性が高まります。
最初から本命1点で出した結果には、要件を満たせたかどうかという価値しかありませんが、4点目として実測した本命の結果には、その数値となる理由が得られ納得感があり、なによりその先も理由を付けて推測できるという、全く価値が異なる試験結果となります。
この例では単位を vCPUs と RPS にしましたが、インスタンス数など他の単位でも同様に『傾向を読み取り推測する』ということに変わりありません。
条件の変更は1つずつ
負荷試験は様々な条件において、場合によっては何度も実行することになります。綺麗に1回ずつ試験して終わり、ということも稀にあるかもですが、たいていはどこかで怪しい結果が出たり、アプリケーション・サーバー側の調整後に再試行するからです。負荷クライアント側では、同時接続数やリクエスト間の間隔時間を調整しますし、サーバー側はインスタンスタイプや台数、アプリケーションのチューニングをします。
何度もいろんな条件下で実行している中で結果の整理を怠ると、条件と結果の紐付けを失ったり、試験の信憑性が疑わしくなることがあります。それを防ぐには、条件の変更は必ず1つずつ行って記録します。
結果は表やグラフとして記録していきますが、それはベースとなる固定条件において、ただ1つの変化であるX軸に対してY軸に計測値を記録します。計測の途中で、ベースのうち小さな設定でも変えてしまうと、その記録はほぼゴミになってしまうということです。
同時に複数の条件を変更したときの結果が、その前の結果と比べて想定外のズレが生じた時、その原因が複数の条件のうちどれなのか、または全てが作用したのかがわからなくなります。
もっとひねくれて考えるならば、仮にズレずに綺麗に比例したとしても、2つのうち片方により向上して、もう片方により劣化したことで、ちょうど釣り合いが取れてしまった結果かもしれなく、でもそれはやはり認識できないでしょう。
何度も何度も実行していると、面倒になることがあります。そういう時に、条件の変更を同時に複数したり、X軸の増加を一部飛ばして省略したり、をしてしまいたくなったとしても堪え、1つずつ丁寧に変更と記録を行うほうが、結局はより早く正確で納得感のある結果にたどり着きます。
当たり前のようですが、データの網羅・正確性を第一に、横着はしない。というピュアな心を大事にしましょう。
例外の炙り出し
線の結果を採取していると、突然傾向が変化したり、そもそもエラーが発生して計測以前の状態になることもあります。これはむしろ、そういう想定外の現象を炙り出すほうが試験のメインの目的だったりします。例外の原因は様々ありますが、クラウドやハードウェア・OS・ミドルウェアの設定値や上限値によって、品質が劣化したりエラーになるので、比例に近い正常値を保ってその続きをするには解決する必要があります。
この例では同時接続ユーザー数が 4000 から急に性能が伸びないことを読み取れます。この現象と数値には、必ず原因があるので、原因を突き止めて解決可能か考えます。
解決するということは、原因を特定し、原因と負荷量との関連性を読み取り、設定変更や可能であれば自動化によって恒久的な解決まで持っていくということです。
負荷試験というと負荷をかける手法に話が行きがちですが、結局は本番より先立って、無理やり課題発掘と解決をしているに過ぎないので、『構築』『運用』の基本セットなくして成り立たず。な業務であることもまた真です。
特異点を捉える
負荷試験を実行して得られる結果には大きく2種類あります。それはクライアントとサーバーのデータです。ここでいうクライアントとは負荷試験システムのことで、大量のリクエストを投げ続けたことによって得られるデータがあります。それは以下のような項目があります。
試験条件によりますが、正常な結果はたいてい、微小なブレがありつつも比例もしくは平坦なグラフになります。その想定する形状ではない部分が現れた場合、そこが特異点と判断できます。
上記項目でいえば、RPSの伸びが悪くなった、接続数が増えなくなった、レスポンスタイムが遅くなりだした、突然エラーが増えた。などです。
そういう現象には必ず原因があるので、次のようなサーバーのデータを並行して確認していくことになります。
メトリクスは種類が多々あるのでここでは例をあげませんが、サーバーの役割ごとに適切なメトリクスを残しているとするならば、特異点の同タイミングで異常な上昇率や、天井張り付きの形状を見つけることができる可能性が高いです。
その項目を発見したならば、関連する設定や処理を特定し、解決に向かいます。
同じように、同タイミングでエラーログが残されているならば、それを手がかりに原因を特定します。エラーログも発生数をグラフにしたり通知すると便利ですが、そもそも発生を可能な限りゼロを目指したいモノなので、記録されたものを片っ端から解決していく、という運用でも十分です。
それらを解決していき、最終的には、想定通りの綺麗な変動値の結果になった上で、目標とする規模でも正常稼働することを証明します。
頑張ればどのようなシステムでも綺麗に収まる、とは言い切れませんが、収まらない場合はたいてい、凌ぐ工夫を考えたり、アーキテクチャから再考することが妥当なので、低い納得感のまま突っ走ることだけは避けましょう。
費用と時間の節約にも
最小リソースから始めることには、費用と時間の節約にも効果があります。試験環境の準備から動作保証までは、それなりに時間がかかりますが、いきなり大構成を準備すると要素が多く複雑になり、苦労しがちです。最小構成だと幾分かは楽になるので、基本となる動作保証までたどり着きやすくなります。
人間誰しも、多くの要素に対峙すると混乱しやすいので、まずは最小でベースを確固たるものとし、そこに肉付けしていく流れのほうが、より早く安定した環境になる可能性が高いです。
また、試験を開始するとたいてい、何かしら予期せぬ不良にブチ当たるので、そういった修正や調整にもある程度時間がかかると思ったほうがよいです。
そしてその時間を大構成でやってしまうと、その間の費用も多く積み上がってしまうので、お財布に優しくない負荷試験になってしまいます。
最初から最後まで大構成なのか、最小から始めて最後だけ大構成なのか、で考えると、得られる結果の品質だけでなく、全体の作業にかかる費用と時間にも大きな違いが出ることを予想できるはずです。
昔のサービスは徐々にトラフィックが増えたものですが、現在は急激に増えたり、最初から大流量だったりするので、負荷試験の重要性はとても高いものとなっています。
より正確・効率的に、想定する負荷での動作保証をし、そのさらに先まで考えられる負荷試験にすることで、いざ勝負所でポシャらないよう仕上げていきましょう:-)