ニフクラ ブログ

ニフクラ/FJ Cloud-Vやクラウドの技術について、エンジニアが語るブログです。

できる!ソーシャルアプリ(3) JMeterによる性能試験で「もう負荷も恐くない」

こんにちは、株式会社エクストーンの仲山です。
この連載では、ソーシャルアプリの企画から公開、運用までを通したTIPSを紹介します。

前回の記事では、 開発環境の構築を楽に行うためのツールとして、 ApacheのVirtualDocumentRoot機能と、システム管理ツールChefを紹介しました。

今回は、ソーシャルアプリと切っても切れない縁のあるサーバーの負荷とうまく付き合っていくため、 性能試験によって計画的にアプリの性能を向上させる方法として、 アプリの性能試験ツールであるJMeterを紹介します。 この記事で紹介するJMeterのサーバー・クライアントモードをニフティクラウド上でうまく使うことで、 アプリに限界まで負荷をかけることが安価に実現できるので、 リリース後の負荷を必要以上に怖がる必要もなくなり、幸せな気持ちでリリースができます。

性能試験の目的

まず最初に、ちょっと想像してみてください。
コンセプトはとても自分の趣味に合うし、登場人物も魅力的で、先を読むのがとても楽しみな小説があったとします。 でも、紙の質が悪く紙と紙が張り付いていて、ページをめくるのに30秒ぐらい掛かってしまうとします。 おそらく、どんなに続きが気になっていても、読むのを止めてしまうのでは無いでしょうか。

アプリも同様で、どんなに面白い内容だったとしても、 サーバーが常に過負荷状態で、サーバーの表示に時間が掛かってしまっては利用者が離れてしまいます。 その一方で、予算には限界があり、無限にサーバーを用意するわけにもいきません。

そこで、 第1回でも触れたとおり、 達成すべき目標性能を決め、性能試験で達成できるかを確認することが重要となります。 また、もし目標性能を達成できなかった場合に、 何がボトルネックとなっているのかを調べることも必要です。

性能調査は、以下のようにいくつかの段階を経て実施します。

<目標性能を達成しているかどうかの確認>
1. 基礎性能 (秒間アクセス数を徐々に増やしていき、性能が劣化するアクセス数を確認)
2. 目標性能 (想定PVに基づいた秒間アクセス数で負荷を掛けたときに、表示に掛かる時間を確認)
3. 限界性能 (表示時間が限界値(例:5秒)を超えない範囲で、秒間アクセス数をどこまで増やせるかを確認)

Jmeterpattern02

<ボトルネック解消のための調査>
1. アプリの様々なページの中で、表示に時間が掛かっているページの特定
2. システム全体で、負荷が高まっているサーバー、プログラム、DBクエリの特定

Jmeterbottleneck

<高負荷状態での動作確認>
1. 高負荷状態においても、処理が正しく行われ、あるべき表示内容が出力されているかどうかの確認
2. 想定を超えた負荷が掛かったときにも、想定範囲内でサービスが停止するなどし、データの喪失などが発生しないことの確認
3. 高負荷時にサーバー増強などで負荷を減らすための手順の確認

性能試験の全体の進め方やJMeterの基本的な利用方法については、 ソフトウェアテストシンポジウムのサイトに分かりやすい講演資料がありますので、 今回の記事では割愛します。 また、今回の連載では触れませんが、性能試験以外のソーシャルアプリ全般のテスト自動化についての講演資料もありますので、 こちらも合わせてご紹介します。

JaSSTソフトウェアテストシンポジウム-JaSST'07 Tokyo
    ・テストツールはじめの一歩1:Apache JMeterで負荷試験をしよう!
JaSSTソフトウェアテストシンポジウム-JaSST'11 Tokyo
    ・ソーシャルアプリケーションのテスト法 -ソーシャルアプリという獣を手懐けるテストのアプローチ-

性能試験ツール JMeter

今回は、アプリに負荷を掛けその性能を測定するための性能試験ツールとして、 Apache JMeter(以下JMeter)を紹介します。 JMeterはオープンソースで開発されているJava製のアプリケーションで、 あらかじめ作成した「テストプラン」に基づいてサーバーにアクセスし、 その処理時間・スループットを確認したり、応答結果の正しさを検証したりできます。

Jmetergraph

性能試験ツールには他にも、 Apache HTTP serverに付属のabコマンドや、 Microsoft社が提供するWeb Capacity Analysis Toolなど、 無償有償様々なものがありますが、若干JavaによるGUIに不満があるのを除けば、 性能試験のために必要な機能がJMeterには揃っています。 また、後ほど紹介するJMeter Plugin for OAuthのように、足りない機能を追加することも可能です。

性能試験を行う上での注意点

性能試験の全体の流れは、上でご紹介した資料が分かりやすいですが、 見落としがちな点がいくつかあります。

1. 初期データ量の重要性

データベースは、ほとんどの場合データ量が多ければ多いほど処理に時間がかかります。 逆に、どんなに無駄が多い処理でも、データ量が少なければその処理時間は微々たるものです。 ですので、利用者のデータや、実行ログのような時間で増えるデータは特に、 性能試験を行うときには、あらかじめ「水増し」した状態を用意する必要があります。

どれぐらい水増しをすればいいのかというと、 あなたのアプリの性能目標を元に算出します。 全体の会員数や、その会員それぞれに対してアプリ内で保存が必要なデータの量、 あとは1日の想定PVから、そのうちログ記録が必要なPV数などを、 アプリの動作を元に仮説を立てて算出します。

2. 利用者の行動の想定

性能試験の目的は、アプリが実際のアクセスに耐えられるかを確認することなので、 テストシナリオの理想は、実際の利用者の行動そのものを記録して再生したものになります。 実際に行動ログを元に性能試験を実施しているケースもあるそうですが、 なかなかそこまでやるのは難しいため、 利用者の行動を単純化した仮説をテストプランとして作成します。

計画的に性能を向上させる方法

このように、 初期データ量や、利用者の行動は「仮説」を立ててそれを元に性能試験を行います。

もし、現実にアプリを公開後のデータ量や、利用者の行動がこの仮説と大きくずれていなければ、 アプリのリリース後にサーバーが過負荷で表示が重くなることはないでしょう。 その一方で、この仮説に誤りや見落としがあれば、 その部分で意図せぬ負荷がサーバーにかかってしまう可能性があります。 そのため、リリース前に計画的に性能を向上させることが重要です。

Pdca02 このサイクルが、性能試験におけるPDCAサイクルとなります。

JMeter Plugin for OAuth

JMeterはそれ自身がオープンソースのJavaアプリというだけでなく、 Pluginとして機能を追加することが出来ます。 そのひとつに、JMeter Plugin for OAuth(以下OAuthプラグイン)があります。

第1回にも書いたとおり、 サーバーへのリクエストはSNSのサーバーを経由して送られますが、 その時に「そのリクエストが正しくSNSのサーバーから送られたものであること」を確認するため、 全てのリクエストにOAuthという規格に基づいた一種の電子署名が送られます。 JMeter等からリクエストを送る場合には、サーバー側でこのOAuth署名の確認を外すか、 JMeter側でOAuthの署名を付与する必要があります。

Oauth

OAuth署名を作るにはSHA1等のハッシュ関数を利用する複雑な計算が必要ですが、 このOAuthプラグインを利用することで、 通常のHTTPリクエストと同じように簡単にOAuth署名付きのリクエストを送ることが出来ます。

サーバー側のOAuth署名を確認する処理を外してしまうと、 その部分に問題があった場合に、想定外の負荷が発生してしまう可能性が生じます。 このOAuthプラグインを利用することで、SNSサーバーから送られてくるのと全く同じ処理で、 性能を確認することができるようになります。

一方で、JMeter側でリクエストを送信するたびにOAuthの署名を計算するため、 この部分がJMeter側の負荷となってしまい、 送りたいだけの秒間アクセス数をサーバーに送ることができなくなってしまう場合もあります。 そのため、自分のアプリの性能試験にOAuthが含めるかどうかは、 その性能試験の目的にそって判断します。

JMeterクラウド

さて、前述のOAuthプラグインであったり、 実際の利用者の行動に近い複雑なテストプランを用意した結果、 アプリに負荷をかけるはずのJMeter側が過負荷になってしまい、 アプリに十分な負荷をかけることができなくなる、ということが起きます。 また、想定するアクセス数がそもそも多く、 実際にアプリのサーバー構成も数十台用意をしているような場合も、 1台のPCで動かしたJMeterからは十分な負荷をかけきれなくなります。

こんなこともあろうかと、JMeterはサーバー・クライアントモードがあり、 一つのクライアントから、実際にアプリにリクエストを送る複数台のサーバーを一括制御することができます。

Jmeterserver

サーバー側の準備

サーバー側も同じJMeterの配布ファイルを使いますが、jmeterコマンドのかわりにjmeter-serverコマンドで起動します。 面倒なので、シェルスクリプトを用意しました。
シェルスクリプト: http://yum.xtone.co.jp/scripts/jmeter-install.sh

これを実行すれば、/usr/local 以下にJMeterをインストールして、jmeter-serverを起動します。
一旦jmeter-serverを終了させた場合も、 /usr/local/jakarta-jmeter-2.4/bin/jmeter-server を直接実行すれば大丈夫です。

クライアント側の準備

クライアントとサーバーは相互に接続を行う、 つまりJMeterサーバーからJMeterクライアントに対しても接続できる必要があり、 社内ネットワーク等でNATやファイアウォールが中間にあると利用できません。 いくつかの方法があります。

MacOSXやLinuxの場合 (SSH X Forwardingを利用)

ニフティクラウドのインスタンス上にjmeterをインストールし、 ssh -X コマンドで接続することで X forwarding 機能を利用でき、 インスタンス上で起動したJMeterクライアントの画面を直接ローカルで表示できます。

あらかじめ、JMeterサーバーのIPアドレスを、bin/jmeter.properties の remote_hosts 行に設定しておく必要があります。 これは、以下の全ての環境で同様です。

Windowsの場合 (VNCを利用)

WindowsにはX window systemが入っていないため、 VNC(x11vnc)等を利用することで、 同じようにニフティクラウドのインスタンス上で起動したJMeterクライアントの画面をローカルに表示できます。

Windowsの場合その2 (Windowsインスタンスを利用)

もうひとつの方法として、ニフティクラウドでは、LinuxのCentOS5環境の他に、 Microsoft Windows Server 2008 R2のインスタンスを利用することができます。 このインスタンスを利用し、リモートデスクトップを経由しての動作が可能です。

コマンドライン実行

あらかじめGUI環境で作成したテストプランをJMXファイルに保存し、 コマンドラインからJMXファイルを指定してテストを実行することもできます。 リアルタイムでグラフ等を見ることはできませんが、 GUI表示自身がJMeterの負荷になりますので、 十分にテストプランの用意が出来てからはこの方法がおすすめです。

/usr/local/jakarta-jmeter-2.4/bin/jmeter -n -t example.jmx -r

この場合、テストの結果を自動で保存するため、 テストプランにシンプルデータライタを含めて置く必要があります。

テストが終わったら、 シンプルデータライタが出力したデータファイルをGUI環境に持ってきて、 以下のようにグラフや統計のサンプラーにインポートすることで、 テスト結果の分析を行うことができます。

Jmeterimport

クラウドと性能試験

ニフティクラウドを初めとしたクラウド環境では、 1時間単位でサーバー契約ができますので、 このように性能試験を実施する間だけJMeterサーバーの台数を増やすといった用途に向いています。 上に書いたとおり、JMeterサーバーのセットアップはシェルスクリプト一つで可能ですので、 性能試験を行う直前にサーバーを追加し、終わったらすぐに解約できます。

メモリではなくCPU性能が必要となるため、 仮にニフティクラウドでCPUコア数が最も多いLargeタイプを利用したとしても、 10台借りても1時間840円で相当大きな負荷をアプリにかけての性能試験が可能です。

リリース前に、目標性能を余裕を持ってアプリが提供できることさえ確認しておけば、 リリース直後のアクセス殺到を恐れることもなく、 サーバーあたりの限界性能が分かっていれば、 必要に応じてサーバーの台数を調整することも容易にできます。 これでもう、サーバーの負荷を必要以上に怖がる必要はなくなります。

次回予告

次回は、リリース環境で複数のサーバーへのアクセス振り分けに必要となるロードバランサーや、 サーバー管理用に安全なネットワークを構築するためのVPNを、 ニフティクラウドの標準機能ではなく、オープンソースソフトウェアを利用して構築する方法をご紹介します。
第4回: オープンソースで「L7ロードバランサーも、VPNも、あるんだよ」