2012/11/06 15:05にTech Blogにて公開された過去エントリです。
livedoor Techブログ : 自家製 #isucon2 のつくりかた

--
こんにちは、tagomorisです。ISUCON2 というイベントで主にレギュレーションを考えたりベンチマークツールを作ったりしていました。普段はNHN Japan ウェブサービス本部というところで働いています。
先日ISUCON2は幸いにも大好評のうちに終了しましたが、このお題および関係する話題をぜひ多くの人にも知っていただきたい! というかこのまま捨てるとかちょっともったいない! ということもあり、作業対象のアプリケーションコード、およびベンチマークツール一式を公開しています。
このエントリでは、これを用いて一式を動作させ、ご家庭でもISUCON2を再現できるよう、いくつかの手順をご説明していきます。ぜひみなさんも楽しいISUCON2ライフを満喫してください。


ざいりょう


今回は初期データはすべてWebアプリケーションのコードから投入されるため、このソースコード一式があればすべて本番時と同じように動作します。

ベンチマーク設定が本番時と同じ設定になっているため、たとえばノートPC1台ですべて動作させようと思うとかなり重いでしょう。その場合にはベンチマーク設定を変更します(後述)。

したごしらえ

ISUCON2環境を作成するPCですが、以下のものが動作する環境が必要です。カッコ内のバージョンはISUCON2本番環境で選択したものです。
  • ベンチマークツール
    • Node.js 0.8.x (0.8.12)

    • MySQL 5.x (5.5)

    • http_load

  • 対象アプリケーション(言語についてはどれかひとつ)
    • MySQL 5.x (5.5)

    • Perl 5.x (5.16.1)

    • Ruby 1.9.x (1.9.3)

    • Python 2.7 (2.7.3)

    • Node.js 0.8.x (0.8.12)

    • PHP 5.3- (5.3)

    • Java 6

各言語のインストールについては perlbrew, rbenv (or rvm), nodebrew (or nvm) などを用いるのが便利だと思います。手元で既にインストールされている場合はそれを使ってください。Perlについては System Perl が 5.8 の場合は、perlbrewを使って新しいものを入れることをお薦めします。
またリバースプロキシを用意する場合、ISUCON2では Apache 2.2 がデフォルトで用意されていましたので、それにあわせて用意してください。
お手元で試すぶんにはOSを縛らなくて良いと思います(ISUCON2ではCentOS 5.8でした)が、http_load を動作させる必要がありますので Linux や Mac OSX などがよいでしょう。Mac OSXの場合にはXcodeのインストールが必要です。
MySQLはそれぞれインストールを行ってください。Linuxの場合はおそらくディストリビューション側でパッケージが提供されているでしょうから、それを使ってもよいでしょう。Oracleのダウンロードサイトで提供されているものを使ってもよいと思います。

ISUCON2本番時のデフォルト設定がリポジトリ中の webapp/config/database/my.cnf にあります。ISUCON2本番時のサーバスペックに近い環境で試す場合にはこれを使ってもよいかもしれません。PC1台だけで試すならパッケージのデフォルト設定などでもとりあえず良いでしょう。


つくりかた

なにはともあれ、ソースコードを取得します。適当なディレクトリを選んで git clone しましょう。isucon2ディレクトリの中に展開されます。
$ git clone git://github.com/tagomoris/isucon2.git
$ cd isucon2

Webアプリケーションを動作させるため、まずMySQLでスキーマの設定を行います。
$ mysql -u root < webapp/config/database/isucon2.sql

Perlでアプリケーションを動作させるには以下のようにします。cpanmコマンドで多少時間がかかります。
$ cd webapp/perl
$ ./cpanm -n -Lextlib --installdeps .
$ perl -Mlib=extlib/lib/perl5 extlib/bin/plackup -s Starman -E production --preload-app app.psgi

これを起動した時点で http://localhost:5000/ にブラウザからアクセスし、以下のような画面が出ればアプリケーションの準備はもう完了です。

isucon2howto_1_app_init


http://localhost:5000/admin にアクセスすると「データ初期化」というボタンがあります。これを押してから再度 http://localhost:5000/ に戻るといくつかチケットが買える状態になっていますので、試してみましょう。エラーもなくチケット購入が完了し、購入した番号のシートが横の購入履歴などに反映されていればOKです。
他の言語でもほぼ似たような手順でアプリケーションが起動可能です。言語ごとのディレクトリに README があるのでそちらを確認してみてください。特に難しいところは無いと思います。
リバースプロキシを設定する場合にはApacheで mod_proxy (やmod_proxy_balancer)を使用する設定を記述します。これは簡単に試すなら行わなくてもよいでしょう。

今回は詳細を割愛しますが、前回のISUCON環境のつくりかた などにも説明がありますので、実施する場合は参考にしてください。
ベンチマークの準備としては http_load のビルドが必要です。パッチをあてたものが tools/http_load_isucon2 にありますので、これを用います。
$ cd tools/http_load_isucon2
$ make

またベンチマークツールに必要なモジュールのインストールを行います。
$ cd tools
$ npm install

これで簡単なベンチマークが動作します。開発時に手元で試すためのコマンドを用意してありますから、それを使うのがよいでしょう。以下のコマンドで localhost:5000 に対して簡単なベンチマーク(本番ISUCON2の縮小版的なもの)が走ります。
$ cd tools
$ ./test.sh 127.0.0.1 5000

完了したら標準出力にJSONで結果情報が出力されてきます。"err" に何も出てなければ基本的には通っていると思ってよいですが、"error" や "timeout" (HTTPステータスがエラーのレスポンス、もしくはレスポンスがタイムアウトした数)が多過ぎる場合はダメかもしれません。

だいたい以下のような結果になると思います。(これは自分の MacBook Air 上で実行したものです。見易いように整形しました。また"buyer"は複数表示されるはずですが、省略しています。)
{ "name": "starter",
"err": null,
"result": { "result": "success" }
}
{ "name": "checker",
"err": null,
"result": {
"get": { "success": 9, "timeout": 0, "error": {} },
"buy": { "success": 1, "soldout": 0, "timeout": 0, "error": {} },
"first_soldout": null
}
}
{ "name": "httpload",
"result": { "status": { "200": 255 },
"fetches": 255
}
}
{ "name": "buyer",
"err": null,
"result": {
"get": { "success": 30, "timeout": 0, "error": {} },
"buy": { "success": 10, "soldout": 0, "timeout": 0, "error": {} },
"first_soldout": null
}
}

ここでの "buyer" および "checker" の "buy" の "success" 数を合計したものが時間内に売れたチケットの数ですね。基本的にはISUCON2ではこれを競うことになります。これが8192に達した場合には "first_soldout" に表示される数値(の最も小さいもの)が完売所要時間のため、これを小さくするのが目標です。


もりつけ

さてこれだとスコアがわかりませんし、結果の把握や管理もちょっと大変です。なのでベンチマーク管理用のツールを起動しましょう。
ベンチマークツールは tools にある manager.js および agent.js を使用します。これらの設定ファイルはそれぞれ config.json と agent.json ですが、デフォルトでは localhost:5001 と localhost:5002 でそれぞれ起動するようになっているので、1台だけで試す場合にはこのまま使うのがよいでしょう。
まず manager が参照する結果保存用のデータベースおよびテーブルをMySQLに作成し、それからmanagerを起動します。
$ mysql -u root < sql/isumaster.sql
$ node manager.js

起動後、ブラウザで http://localhost:5001/ を見ると次のような画面が見られるはずです。

isucon2howto_2_manager_init

これがISUCON2でも使われた管理画面ですが、このままだとエージェントが起動していないためベンチマークが実行できません。エージェントを以下のコマンドで起動します。
$ node agent.js

そうすると数秒で管理画面が以下のように変わるでしょう(右下に注目!)。こうなるとベンチマークを実際に走らせるエージェントが準備できていますので、あとは実行するのみです。

isucon2howto_3_manager_agents

なおベンチマーク実行前に管理画面でログインが必要です。config.json の "users" にログイン用のユーザ名とパスワードリストがありますので "manager" ユーザを使うとよいでしょう。デフォルト設定では "local" チームを選択すれば localhost:5000 に対してベンチマークが走るので、先程立ち上げたアプリケーションのスコアが確認できます。

isucon2howto_4_result

やってみたらFAILEDになりました……。高い並列数に対応できず、接続に失敗したHTTPリクエストが多数あったようですね。原因がわかれば、あとは改善あるのみ!


かくしあじ

なお上述の各プロセスは普通に起動すると端末をブロックしますから、本格的に時間をかけてとりくむなら supervisord などを使用して常時バックグラウンド起動する環境を作ると良いでしょう。
マシンを複数台使える場合にはアプリケーション起動用とベンチマーク実行用に分けるといいと思います。分散構成をとるには以下のようにします。
  • アプリケーション側
    • リバースプロキシサーバ(1台)、アプリケーションサーバ(1台もしくは複数台)、データベースサーバ(1台)

    • アプリケーションに対する接続先データベースの指定は webapp/config/common.${env}.json で行われているので、これを変更しましょう

  • ベンチマーク側
    • manager(1台、MySQLもここに)、agent (1台もしくは複数台)

    • agent.json にmanagerのIPアドレスおよびポートを指定して起動します

またPC1台のみ、あるいは比較的非力なサーバマシンのみで実行する場合、ISUCON2本番のベンチマーク設定ではちょっと負荷が高過ぎるかもしれません。ベンチマークツールからの接続エラーなどがどうしても頻発する場合、 manager.js の先頭にベンチマークの各部分における並列数・起動プロセス数が書いてありますから、これを減らして manager を再起動してみましょう。

できあがり

これで環境は完成です。思う存分にあなたのISUCON2をお楽しみください! 高得点をゲットできたらblogなどに書いていただけると我々もとても嬉しいです。
NHN JapanではISUCON2と楽しく激しく格闘できるエンジニアを募集しています!