ISUCON模試を開催して運営&参加してきた
沖縄の宜野湾市にあるプロトソリューションさんが運営するCODEBASEでISUCONの模擬試験を開催してきました。 ここ最近ぼくがISUCON, ISUCON行ってたら一緒にイベントやろうと言って頂いたので開催する形になりました。
今回、題材をいつも使わせてもらっているpixiv private-isuを今回も使おうかなーと思ってたのですが、周りで数回模試をやってたりすると参加者の半分ぐらいがすでに一度やったことある経験者が多かったのでせっかくの機会にまた同じものをやってもなーと昨日思いながらとtwitterのタイムライン見てたら、ふとISHOCON1 〜個人参加のISUCON練習コンテスト〜というのが開催されていることを知り、その題材となってるishocon1のリポジトリが公開されていたので、あれこれいけるんじゃねと思い急遽こちらを使うことにしました。
参考実装はRuby, Python, Goで用意されててEC2のAMIが公開されていたり、マニュアルがちゃんと書かれていたりで構築のハードルが低くて運営としてすごい助かりました。ISHOCONを作成して公開していただいてる @showwin さんに感謝です。
※AMIが公開されてるの利用者側としてはとっても重要なので用意してもらえると利用者としてはとてもやりやすく普及し易いと思いますのでやってみてもらえるといいのではと思いました。
運営としてやったこと
インスタンス構築
AWS EC2のインスタンスはCODEBASEさん側で用意してもらえる事になっていたので、参加チーム分作成していただきました。今回は8台のインスタンスを構築しました。ISHOCONでは競技用のアプリとbenchmarkerが1台の構成なのでチームに1台インスタンスという構成になります。
公開鍵の設定
参加者の方には事前にGithubへアカウント登録してもらい、各自公開鍵の設定をお願いしていました。今回はGithubの公開鍵を利用して、各サーバーに割り当てられた参加者と管理者の公開鍵を設定しました。
$ curl https://github.com/{saboyutaka,tompng,siman-man}.keys >> /home/ishocon/.ssh/authorized_keys
動作確認
各インスタンスに入り、マニュアルにかかれている手順でアプリを起動し、ベンチマーカーが動くことを確認しました。事前に @showwin さんに利用確認をした際に、一部バグが存在しているので修正してくださいということを伺ったので、その部分を全インスタンスに反映させました。
ポータル
ポータルは pixiv private-isu で利用するために公開されてるポータルを流用しました。
ポータルの構築自体はポータルの説明どおりに構築しました。ISHOCONのbenchmarkとポータルが必要とするJSONの形式が異なるためどうしようかなぁと思ったけど結局雑なスクリプトを使うことで対応しました。前日に急遽思い立って変更したのであまり時間がなかったのでまぁいいかなと。 ポータルではscoreとtimestampだけが利用されていたので、その形式でJSONを投げることにしました。
#!/bin/sh TEAM=$1 SCORE=$2 JSON="{ \"score\": ${SCORE}, \"timestamp\":{ \".sv\":\"timestamp\" } }" curl -X POST -d "${JSON}" "https://xxxxx.firebaseio.com/teams/${TEAM}.json"
これを全員にダウンロードしてもらい
./score.sh team名 12345
のように実行してもらう形にしました。点数は自己申告です(笑)
そのほか
これで環境構築はだいたいできたので、あとは開始の挨拶とレギュレーションの説明なんかを軽くしました。参加者の皆さんがISUCONについてご存じの方が多かったので負担がほとんどなかったので良かった。
参加者としてやったこと
運営準備がわりとスムーズに行えたので、競技開始時間から20分後くらいには競技に参加することができた。今回は okinawa.rbのメンバー(@tompng, @shiman-man)とチームで参加しました。2人がアプリケーションがっつりかける感じだったのでぼくはインフラ周り担当しますねーという感じでやった。
今回もおなじみのツール群を使いました。
時系列あまりちゃんと覚えてないので以下やったこと。
- webapp配下をgit repository化、githubにpush
- mysqldumpで競技用インスタンスのDBをdump
- ローカルでgithubからclone、dumpからDBを再現構築
- Rubyのバージョンアップグレード 2.2.3 -> 2.4.2
- bundle update
- nginx.conf, my.cnfをgit repository配下に移動
- おれおれMakefile
- alpのインストール
- myprofilerのインストール
- htop, tig, tree, pecoあたりをインストール
- nginxの設定
- 静的ファイルをnginxで配信(これは今回効果なかったっぽい)
- その他細かいやつ、秘伝のタレを利用
- mysqlの設定
- innodb_buffer_pool_size, query_cache あたりを中心に秘伝のタレを利用
- gooseを使ったmigration環境の構築
- 各テーブルのindexを貼る
- imagemagickを使って画像のresize
- sessionをmemcachedで管理
- nginx update 1.8.x -> 1.12.0
- mysql update 5.5 -> 5.6
- mysqlのデータベースをinnodb_file_per_tableするために一度DROPして再構築
- nginx, unicorn, mysqlをunix domain socket での通信に変更
- app.rbのいくつかのチューニング
- 定期的にhtop, alp, myprofilerの状況報告
- portalへのPOST
- benchmark回す担当
- ポストイット整理
実際のコード github.com
開始前にこれはやりたいなぁと思っていたものは一通り消化できたので満足。今回のアプリは画像をリクエストしてくるときにheaderを送ってきてくれてない?ぽくてnginx側でexpiresつけてたけどその後も普通にリクエスト投げてくるので304返せなかった。画像は400px幅しか使われていなかったのでリサイズしてみたところbenchmark通ったのでこれで行くことにした。N+1も削りつつ、ほとんどのDB問い合わせを@tompngさんがゴリゴリキャッシュしてくれてったおかげで爆速に。
結果優勝することができました!🎉🎉🎉
あまりアプリケーションコードそこまで読まなくておまかせしてたのでスコア取れたのは大部分 @tompngさんと@shiman-manさんのおかげ🙏🙏
学生チームのMK5(@d_ishitaka, @CodeHex, @maeken2010)と接戦してたけど、勝てて大人の尊厳をまもれてよかった。学生でここまでできるのやばい。
まとめ
今回もめちゃくちゃ楽しくやらせていただきました。運営、会場提供、イベント企画をしていただいたCODEBASEさん、題材のISHOCONを作成・公開していただいている@showwinさん、また参加していただいた皆さんありがとうございましたー!!
予選がんばりましょー!!💪💪💪