tkuchikiの日記

Linux やプログラミングについて書きます。

ISUCON3 本選に出場してきました 【インフラ編】

はじめに

11/09 (土) に行われた ISUCON3 本選に、会社の先輩 @hilotter と、同期の @Konboi で、カヤック選抜「流れ弾」として参加しました。
言語は Ruby を選択しました。

結果から申し上げると、最終計測で Fail するという選抜チームとしてあるまじき結果となりましたが、終盤までは TOP 争いを繰り広げ選抜チームとしての役割を少し果たせたかなと思っております。

当日までの準備

予選では、nginx で ltsv 形式のログを吐いて、レスポンスタイム順にソートできるようにする準備はしていましたが、

apache で計測する準備ができていなかったので、同じようなことをできる準備をしました。
他には、capistrano 3 でデプロイできるようにしたり、github にプライベートリポジトリを用意したりしました。
準備をしたものは、大部分を gist にまとめていますので、末尾に記載します。

当日

受付 〜

f:id:tkuchiki:20131111195656j:plain

受付を済ませて、無線 LAN に接続できることを確認したあとは、@hilotter さんとレッドブルポカリ(私はモンスターポカリ)を作って本選開始に備えていました。

開会式 〜

お題が画像版Twitter という発表を聴いて、画像かー... と早くもダメなんじゃないかと思ってました。

11:00 〜

失敗した場合は、無慈悲なOS再インストール以外の対応は行わないということでしたので、
/home/isucon ディレクトリを圧縮して、ローカルマシンに転送。
圧縮したファイルが 3GB で、この圧縮自体にも結構時間がかかったので、
その間に、各サーバに公開鍵を配って、公開認証できるようにしました。

公開鍵を配り終えて、全サーバにパスワードなしで入れることを確認しても、まだまだ圧縮したファイルの転送は終わりそうもなかったので、
ruby 以外のアプリを削除して、画像データを除いた状態で github に push してチームに共有。

そのあとは、予選同様 starman が起動しているのだろうと思い、予想通り起動していることを確認し、supervisord で動いていることを確認しました。
perl の部分をコメントアウトし、ruby の部分を有効にしてアプリ起動。
mysql slow log の設定と apache の log を ltsv で出力するように設定して、初期状態のまま計測。
一回目何らかの原因で 500 が出てすぐにこけた記憶がありますが、原因は忘れました...

なんやかんやで無事初期計測を終えて、

初期スコア:24. カヤック選抜「流れ弾」	 1380.5

となりました。

12:00 〜

apache のログと dumpslow の結果を見てアプリに手を入れてもらっている間に capistrano の設定をしました。
デプロイするところまではスムーズに行きましたが、
2 回目以降のデプロイで bundler 周りでエラーが出て、嵌りそうだと判断して capistrano の使用を断念。
ファイルを一箇所に集約しないといけないねーという話しになって、なら NFS を使おうと私が提案しました。

一瞬はまった?のが、benchmark を走らせた時に 413 Request Entity Too Large が出てこけましたが、
client_max_body_size を設定してエラーを解消しました。

昼食

f:id:tkuchiki:20131109130144j:plain

色々なお弁当をご用意いただいて、ありがたく頂戴致しました。
美味でした、ありがとうございました。

13:30 〜

昼食をいただきながら、NFS の設定をしていたことは覚えていますが、ここらへんから記憶が曖昧になり、IRC のログも断片的すぎて何をしたか思い出せない...

途中で、/home/isucon/local や、必要なファイルを各サーバに rsync で転送しつつ、全サーバに nginx をインストールし、NFS の設定を 15:30 くらいに終えました。
/var/lib/mysqlrsync で まっさらなサーバに送り、MySQL を起動。
しかし、別ホストから MySQL に繋げなくて 3 人で色々みていたら、bind-address = 127.0.0.1 という記述を発見...
これを修正した時点で、残り 1時間半くらいでした。

16:30 〜

アプリを複数サーバで起動して、ベンチマークを複数サーバに向けて走らせていたらアプリでエラーが出るように。
NFS のせいっぽいなーと思い、検証用の Ruby コードを書いたりしましたが、システムコマンドなら問題無いということを @Konboi がつきとめてくれたので、
各サーバのミドルウェア自動起動設定を確認・設定しました。

17:30 〜

そろそろ再起動かけても動くことを確認しようかとなったときに、reboot の起動順保証されてないから NFS クライアント側は NFS サーバが起動した後にマウントするようにしないといけないということに気が付きました...
NFS はまったくと言っていいほど使ったことがなく、もうだめかなーと思いつつ、

困ったときの crontab だ!
crontab で mount するまで只管 mount -a 打てばいいんだ!

という苦し紛れにもほどがある方法を思いつき、5 分 で全部のサーバに仕込んで残り 2分。
全サーバで cron が走って mount したことを確認して、終了となりました。
終了直前に、各サーバは reboot をかけてアプリが動作していることは確認できましたが、全台 reboot して、ベンチマークが走るところまでは確認できませんでした。

計測中

f:id:tkuchiki:20131109183142j:plain

はしゃいでオフィスの写真を取らせていただいていました。

結果

サーバの設定ができていなかったため、Fail して Score 0...

懇親会

株式会社データホテル様スポンサーでの懇親会を楽しませていただきました。
あっという間に終了の時間になっていました。

反省など

  • NFS を使う場合、再起動時のことやファイルの排他制御など問題になることはいくつかあるにも関わらず、安易にこの決断を下したことは非常に良くなかった
    • 最終計測で Fail したのは私の安易な判断の結果なので、チームの 2 人には大変申し訳なく思っています
  • crontab でどうにかしようとするのが予選のときからの癖みたいになっているので、非常によろしくない
  • 1 分 30 秒差で特別賞を取り損ねましたが、最初は score 50,000 に達したチームという条件で、この条件を満たしたのが LINE 選抜さんだけだったので、この結果でよかったのかなと思っています

最後に

Line株式会社様、株式会社データホテル様、ならびに運営・出題に携わってくださった方々に御礼申し上げます。
とても充実した時間を過ごさせていただきました。

また、チームに誘ってくれた @hilotter さん、@Konboi くんにも感謝します。お疲れ様でした!

その他

システム構成図

構成は以下のとおりです。

  • Nginx 1.4.3
    • Serving static content
    • Reverse proxy requests to unicorns
  • MySQL 5.5.34
  • Unicorn
    • isu241 ~ isu244
      • 8 workers
    • isu245
      • 2 workers
  • NFS
    • Sharing image file
    • isu241
    • isu242 ~ isu245

f:id:tkuchiki:20131113202929p:plain