負荷テストの重要性
今日は負荷テストのお話しでも書きましょう。サーバを構築する際には、様々な要素が複雑に関係し合って性能が決まります。
CPU性能やRAM/HDDなどのリソースの状況、アプリケーションのパラメータなどももちろんですし、インターネット向けのサービスであれば、ファイアーウォールやルーター、ロードバランサーの性能なども関係してきます。もちろん、アプリケーションの作り方自体も大きな影響を持ちます。
これらの要素のうち、後から変更できない要素は、最初の設計時点で決まってしまいます。いわゆるサイジングという言葉で呼ばれていますが、机上の計算だけではなかなか決められず、かといって、高価な構成の場合、とりあえず買って実験してみるというわけにもいかず、なかなか難しいものです。
また、目的に応じて開発するアプリケーションも、性能目標を決めて設計・開発を始めても、実際にその性能が出るかどうかは、作ってみなければわからないことも多いのです。
結果として、システムが組み上がってみたら、全然性能が出ない、ということは、実際によくあることです。
また、ネットワークシステムの場合、負荷が高くなると様々な問題が出ることも多く、排他の問題や、リークなどによるリソース枯渇、例外処理の甘さなどにより、負荷が高くならないと表面化しない問題も多いものです。
そんなときに活躍するのが、負荷試験ツールで、私は2000年頃、ちょうどWEBが業務で本格的に使われ始めた頃に、人を大勢集めて行っていた試験に疑問を感じ、プログラムで負荷試験を行えるように「SADEE」という製品を開発しました。その後、一度完全に作り直して「SADEE2」として、今でも販売を続けながら、自分たちも便利に使っていますし、機能追加も続けています。
WEBに限らず、ネットワーク関連のシステムで負荷試験は不可欠と考えていますので、他にも製品としてはリリースしていませんが、DHCP、メール、DNSなど、様々な負荷試験ツールを都度作って、動作確認を行いながら開発や構築をしてきました。
最近ご相談を頂いたものでは、WEBとVNCを連携させたシステムの負荷試験を行いたいというものがあり、SADEE2と新規に開発したVNC負荷試験プログラムを連携させて実現したりと、とにかく試験対象があれば、なんとか試験を実現させようと取り組んできています。
フリーのツールもいろいろありますので、自力でなんとかしている人も多いと思いますが、意外とツールの使いこなしも難しかったり、あるいは、目的に合う試験シナリオが作れなかったりすることも多いので、当社のように、自分たちで開発したツールをベースに、さらに目的に応じて機能を追加したりしながら実現するということへのニーズもあるのでしょう。
WEBの負荷試験がどんな感じなのかを、SADEE2を例にご紹介しましょう。
まずは試験用のシナリオを作ります。SADEE2では、ブラウザのプロキシをSADEE2のプロキシに向けてアクセスすることによりシナリオを簡単に生成できます。その後、必要なリクエストだけにしたり、あるいはリクエストの内容を加工したりすることも可能です。
この例ではSSLで4個のリクエストを実行しています。SADEE2は、UIの開発時期が古いのでルックスはいまいちです。。
このリクエストを実際に行ってみるのが負荷試験になります。たとえば、10人が同じリクエストを行うようなことを考えると、
こんな感じにバッチファイルを作成します。バッチファイルには様々な記述ができ、リクエストの内容を部分的に書き換えたり(たとえばログインアカウント・パスワードだけ変えるなど)、セッション維持用の情報を指定して動的に置き換えたりすることもできます。
実行してみましょう。
この例では、二人ずつ、10秒ずらして開始するようにしてあるので、負荷試験と言うほどの負荷は発生しません。全て応答コード200番台で戻ってきています。
10人分、同じシナリオを実行したので、それぞれのリクエストのレスポンスタイムを比較することもできます。
グラフにもできます。他にもいろいろな分析の仕方ができます。
同じシナリオを100人、全く同時に開始させると、こんな感じになります。たんなる固定ページを応答するだけなので、ほとんどばらつかずに高速に処理できていますね。
他にも、限界まで負荷をかけ続けるというタイプのテストもできます。
私のMacBookAirの無線LAN経由でも10秒あたりで700個のやりとりができていますね。
もう少し複雑な試験対象の様子もみてみましょう。
今度は、当社のファイルサーバに100個同時で負荷をかけてみました。ログイン処理などの動的な処理もあるので、かなりばらつきます。
この負荷をかけているときの、WEBサーバ側の負荷状況を同時に観察すると、java(ファイルサーバはJavaで動いています)がそこそこCPUを使っていますが、まだ余裕がありそうです。
実はファイアーウォールサーバ側で、リバースプロキシ(java)が忙しくなっており、このプログラムで流量制限もかけているので、WEBサーバ側は余裕だった、という感じに判断できます。リバースプロキシ型のファイアーウォールは私としては珍しくJavaで作ったのですが、先にCで作り、たまにはJavaで作ってみるかと、作って、その後そちらばかり機能追加して、いまだにそのままJavaで動いているのは、ちょっと個人的には不満なのですが、追加機能をC言語版に戻す時間もなかなか取れずに、いまだにJavaです。。
他にも、高負荷を与えて挙動を観察するだけでなく、長期安定稼働試験や、リリース後の監視など、様々な用途に使われています。
本当は、サイジングを検討する時点、システム設計をする時点、開発を進めている時点、テスト、と、全ての段階で負荷試験を常に行っておくのがお勧めです。最初に書いたように、後からではどうすることもできないボトルネックもあるものです。
プログラム開発を担当しているのであれば、一通り作り終えてから試験で性能が出なかったり、致命的なリソース不足や排他障害などが出ても、解決が大変なので、作りながら常に性能を見ておくのはとても大切です。
私がネットワーク関連の開発を行う場合は必ずセットで負荷試験用のツールも作ります。動作確認しながらでないと安心して開発を進められません。
以前はリリースしてから高負荷でサーバがダウン、という事件も結構ありましたが、最近はさすがにそこまでひどいことはあまり耳にしません。しかし、構想・設計段階からきちんと高負荷を考慮して進めているプロジェクトはまだまだ少ないと感じています。最初から高負荷を考えながら進める方がはるかに信頼性の高い構築ができます。SADEE2が万能とは自分でも思っていませんが、いずれにしても負荷試験の重要性はもっと認識されなければと感じています。