Webの負荷テストをEC2上での分散環境で行う。
夢の(悪夢の)TV露出、それに備えて負荷テスト
Webサイト・サービスを立ち上げて順調に成長していくと、ニュースサイトや雑誌に載ったり、運が良ければTVに取り上げられたりする。プロモーション視点で言うと夢の様なTVデビューも、インフラ担当に取っては悪夢でしか無い、と。
不幸中の幸いな事に、TVに取り上げられる場合は日時が決まっているので、事前に負荷テストを行なってチューニング等の対策を行う時間が取れる。
今回はWebサービスの「負荷テスト」を行う方法の一つとして、Amazon EC2上に複数のインスタンスを立てて、そこから対象のWebサービスに負荷をかけていく方法について説明する。
ツール選定
大雑把に絞込み
「負荷テスト」でぐぐるとこちらのページがトップで出てきたのでいくつか調査してみた。結論から言うと、機能的にはJMeter以外はどれも大差なくて、情報の多さ等を考えるとJMeterかab(Apache Bench)の2択となった。
詳細は後述するが、今回は比較的単純なアクセスパターンを想定しているため、シンプルなabをベースに進めることにした。
分散環境でやりたい
負荷テストを行う際に結構あるのが、以下の部分がボトルネックとなってしまう事。
- クライアントのスペック
- ネットワーク帯域
また、(今回のケースでは該当しないが)単一クライアントからだと、ロードバランサーで常に同じWebサーバーに割り振られてしまう場合もあるので注意。
上述の理由もあり(また今までやったこともないし興味があったので)、今回は複数のテストクライアントを用意して、そこから対象のサービスにアクセスすることとした。今回使ったのはBees with machine gunsというやつ。本家は以下の通り。
どういうものかというと、このツールを使うとEC2のmicroインスタンスを指定した数だけ勝手に立ち上げてくれて、そのインスタンスから対象のURLに対してabで負荷をかけるというもの。
ただし、今回はオリジナルバージョンではなく、以下のフォークバージョンを使用。
注意点として、2013/4/22現在、master にはバグが有って正常に動かない模様。masterに取り込まれたこのpull reqが悪さをしているみたいなので、こちらのバージョンに戻して使用した。
想定シナリオ
サービスの内容、構成
テスト対象のサービスの内容としては、登録ユーザーが情報を投稿し、他のユーザーがそれに対して何らかのアクションを起こすというもの。
構成としては以下のようなオーソドックスなもの。負荷テストの結果によってはDBサーバーを複数台にする事も検討。
ロードバランサー - Webサーバー(複数台) - DBサーバー
各ページの処理概要
トップページでは、セッションを開始して、登録済みユーザーかどうかの判別を行う。登録済みユーザーの場合は、ホーム画面にリダイレクト。ただし、今回の想定シナリオでは、アクセスに占める登録済みユーザーの割合は無視出来るほど小さいと想定。
新規ユーザーの登録ページでは、ユーザーテーブルにレコードを追加する。
登録済みユーザーがアクセスするホームページでは、各種テーブルから情報を取得してきてダッシュボード的に表示するため、DB的には一番負荷が高い。新規ユーザーはまだ投稿をしていないため、新規ユーザーのホームページで表示される情報は、
- 運営側からの通知
- 人気の投稿
- 新着の投稿
などに限られる。従って、どの新規ユーザーに対しても、同じ内容のものが表示されるとみなして良い
アクセスパターン
今回はTVに取り上げられ、以下の様なアクセスがある事を想定。
- トップページに新規ユーザーの大量にアクセスが発生
- そのうちの20%が登録を行なって、登録後のホーム画面に遷移(※)
※登録率20%というのは少し高めに見積もった数字
本テストでは、トップページとホームページの2つに対してアクセスを行うこととする。
テスト環境の構築
さて、前述のbees with machine gunsのフォークバージョンを使用。なぜ本家でなくてフォークバージョンを使ったかというと、本家のバージョンは複数URLに対してのテストが出来ないため。
環境
bees with machine gunsは(abを実行するmicro instanceとは別に)EC2上にインスタンスを1台立てて、そこにインストール。
以降、秘密鍵作成等も全てus-east-1リージョンで行うこと。
必要なパッケージのインストール
$ sudo yum install autoconf gcc python-devel python-pip fabric $ sudo pip-python install virtualenvwrapper
AWS関連で必要なこと
AWSのアクセスキーは必要なので取得しておく。
必須ではないが、専用でkey pair作っておくと良い。名前は何でもいいけど、本記事では秘密鍵は loadtest-key.pem という名前という事にする。
これも必須ではないが、セキュリティグループも専用で作っておいてもいいかも。inboundのsshが許可してあればとりあえずOK。今回は sg-loadtest としておく。
各種設定
bees with machine gunsはBotoというライブラリを使っているが、それ用に /etc/boto.cfg あるいは ~/.boto というファイルを以下の内容で作成する必要がある。
[Credentials] aws_access_key_id = <your access key> aws_secret_access_key = <your secret key>
また、秘密鍵 loadtest-key.pem は ~/.ssh 以下にコピーしておく。
次に、virtualenvwrapper 用に .bashrc に以下の内容を追加。
export WORKON_HOME=$HOME/.virtualenvs export PROJECT_HOME=$HOME/Devel source /usr/bin/virtualenvwrapper.sh
インストール!
$ git clone git://github.com/timsu/beeswithmachineguns.git $ cd beeswithmachineguns $ git checkout 0bba9e771fc85da94683547c07328ba75367adf9 # 前述の通り、masterにバグがあるので $ mkvirtualenv --no-site-packages bees $ pip-python install -r requirements.txt
使い方
負荷テストクライアントの起動は以下の通り。以下の例では4台起動している。
$ bees up -s 4 -g sg-loadtest -k loadtest-key
今回の負荷テストでは、以下のURLを4:1の割合でアクセスすることとする。
以下のコマンドで負荷テスト開始。この例ではトータル10000アクセス(1番目のURLに8000回、2番目のURLに2000回)、100並列。詳細はドキュメントを参照。
$ ./bees attack -n 10000 -c 100 -u http://example.com/A,,,,http://example.com/B
負荷テストが終わったら、クライアントのシャットダウン、破棄を行うこと。これを忘れるとお金を無駄にしてしまう。
$ bees down
bees with machine gunsの設定は ~/.bees に保存されるので、何かあったらこのファイルを削除して最初からやり直すとかも出来る。
まとめ
ちゃんと動くようになるまで結構時間がかかったけど、慣れれば便利っす。
本ブログ記事は、作業が終わってしばらくしてから書いたので、不足している情報や不正確な情報があるかもしれないので、もし何かあればご連絡を・・・
最後にお約束の注意事項:自分の管理している以外のサーバーに負荷テスト(というか攻撃)を実施すると、法的に問題になったりするので気をつけてね。