ISUCON3 本選に出場してきました 【祈り編】


チームメンバーのブログ記事

謝辞

LINE株式会社様、株式会社データホテル様、ならびにカヤックの皆様、貴重な経験の場を設けていただきありがとうございました。この場を借りて改めて御礼申し上げます。

はじめに

先日行われた、 ISUCON3 本選@Konboi@tkuchikiと チーム カヤック選抜「流れ弾」として参加してきました。

最初Konboiにチームに誘われたとき、ちょうど「今年はチューニング周りの力をつけねば」と思っていたので、「予選に残れるようにはがんばりたいなぁ」と軽い気持ちで参加しました。

が、その後まさかの

tweet1

ということでじゃんけんに勝って見事、社内選抜に選ばれました。

この時からプレッシャーがものすごくあったのですが、現時点での自分たちの実力に向き合おう、ということで予選には特に対策をせず挑みました。

そして、予選結果は惨敗でした。。。

予選で惨敗してしまったこともあり本選へのプレッシャーはさらに加速です。

当日までの準備

言語は予選と同じくRubyです。

予選では役割分担が曖昧になったのが反省点としてあったので、本選ではアプリ2人、インフラ1人と役割分担を明確にして挑もうということになりました。

本選1週間前に近くの焼き肉屋で3人で密会をして、当日の流れをざっくりとおさらい。

自分は休日の時間を使ってSinatraでRedisのキャッシュを使うアプリを作ったりしていました。

プロファイリングツールに関しても調べてみたのですがよく分からなかったので断念。。。

なんだかんだで本番前日になり、

していたら深夜1時過ぎに。

学生時代のテスト前日の気分でした。

当日

9:45にみんなで集まってコンビニで買い出し。

会場入りしてからはレッドブルポカリの準備。

KonboiはLINEキャラと写真をとってはしゃいでいました。

11:00 〜

  • 11:10くらいまでが開会式とお題(画像版Twitter)の発表
  • サーバ情報が配られたのでとりあえずsshログイン
  • 「初期画像消すと大変なことになるよ」と注意があったので取り急ぎtkuchikiにバックアップを依頼
  • Konboiと一緒にReadmeをじっくり読んで、コードを読む前にまずはアプリの動作確認
  • jquery-1.10.2.min.mapで404が出ているのを発見
  • tkuchikiが鍵を置いてくれたので全台ログインできることを確認
  • tkuchikiにgithubにコードをpushしてもらっている間にKonboiとコードを確認

12:00 〜

  • tkuchikiにslow-logやaccess_logの設定をしてもらって初ベンチ
  • 初期スコアは1380.5でした
  • 画像周りをKonboiが担当することになったので、自分はアプリ全体を見ていくことに
  • access_logのレスポンスタイム降順結果を見たところ、timelineが30秒かかっていたのでtimelineを調査
  • API仕様書とtimelineのコードを見て、long-pollingしているため30秒かかってることが判明
  • timelineの所にサブクエリがたくさんあったので「ここ改善点かな?」と思いながらよく分からなかったのでスキップして他の箇所の調査へ
  • 12:45分くらいに「え?もうこんな時間!?」となってお弁当をいただいた記憶があります
  • おいしい唐揚げ弁当ごちそうさまでした

13:00 〜

  • とりあえずjquery-1.10.2.min.mapで404が出ていたのを解消
  • slow-logとコード内のクエリを見てindexを貼る
CREATE INDEX `follow_map_idx_created_at` ON follow_map (`created_at`);
CREATE INDEX `entries_idx_image` ON entries (`image`);
  • nginxで画像返すようにしてもらおうと思っていたけど閲覧制限の関係でアプリを通さないと難しそうということに

14:00 〜

  • サーバ構成を相談してWEB+APPが4台、DB1台で行こうという話に
  • tkuchikiが残りのサーバのセットアップを開始
  • Konboiの画像周りの修正が終わったので反映したところ、スコアが一気に上がって暫定1位に(6800くらい)
  • 自分はコードを読みながら改善できそうな所を探す
  • 画像変換の所でresque使えるのかなと思ったけどpostしてすぐ表示しているので難しそうと判断

15:00 〜

  • Konboiがworkloadを2に上げてベンチを試したら12000くらいまでアップ
  • その間にtkuchikiがNFSの設定をしてくれていました
  • uri_forのところ、「http://じゃなくて/でいいんじゃない?」と安直に変えたらベンチから画像へのアクセスができなくなってエラー
  • ごめんなさいごめんなさい

16:00 〜

  • DBを独立させ、複数台構成ができてきたのでDB接続先や画像データの保存先を変更してアプリを立ち上げてみたところなぜかログインできず
  • 別ホストからの接続がなぜかできない状態ということが判明
  • 3人で色々調べながら、自分はtkuchikiに「iptalesかなー?」とか「ユーザ登録されてるのかなー?」とかそれっぽいことをつぶやくテディベア役をやっていました
  • 最終的にはbind-addressにトラップがあったことをtkuchikiが発見
  • DBや画像データの保存先を変えるために設定ファイルをいじっていたが、焦ってローカル状態のままコミットしたりして迷惑をかけてしまった
  • ごめんなさいごめんなさい
  • DBにうまく接続できるようになったが、NFSに画像をmvする際にエラーが発生
  • Konboiがシステムコマンドならうまく動くことを発見して反映

17:00 〜

  • signupの時に毎回userをinsetしていたので修正
  • 最終的に自分がコードいじったのはここくらいだった。。。
 -    api_key = Digest::SHA256.hexdigest($UUID.generate)
 -    mysql.xquery(
 -      'INSERT INTO users (name, api_key, icon) VALUES (?, ?, ?)',
 -      name, api_key, 'default'
 -    )
 -    id   = mysql.last_id
 -    user = mysql.xquery('SELECT * FROM users WHERE id = ?', id).first
 
 +    user = mysql.xquery('SELECT * FROM users WHERE name = ?', name).first
 +    if !user
 +      api_key = Digest::SHA256.hexdigest($UUID.generate)
 +      mysql.xquery(
 +        'INSERT INTO users (name, api_key, icon) VALUES (?, ?, ?)',
 +        name, api_key, 'default'
 +      )
 +      id   = mysql.last_id
 +      user = mysql.xquery('SELECT * FROM users WHERE id = ?', id).first
 +    end
  • 残り1時間になったのでアプリの修正はここまでにして、残りはunicornプロセス数の調整やworkloadの設定をすることに
  • サーバの数を増やしてベンチをまわしてスコア22000くらいが出ました
  • 特別賞が25000だったので「もしかしたら特別賞行けるかも!」という希望が見えた瞬間
  • ベンチ後の2分を待ってる間に、LINE選抜チームが40000超えのスコアで一気に一位に
  • 会場が一瞬湧きました
  • @sugyanさんの記事にもあるように、たまたまタイミングが重なっておもしろい展開になったようです
  • さすが何が起こるか分からないのがISUCONだなと思いました
  • そのすぐ後に、30000を超えることができ現状2位に
  • 再起動確認もしなきゃという話になったところで、「そういえばNFSサーバが最初に起動されるとは限らないからマウントうまくできないんじゃない?」ということに気づく。。。
  • 「詰んだかも・・・」と思いつつ、tkuchikiに「いざって時のcrontab」と煽りを入れて、mount用のスクリプトを作ってもらっている間にKonboiと一緒に各サーバにcron設定
  • 残り5分
  • 全サーバでcronが走ってmountしたことを確認し、最後のベンチで35082が出ていました
  • ただ全台再起動しての確認ができなかったので、本番計測はただただ祈るのみ

計測中

レゴブロックでキノコを作ったりしながら祈ってました

tweet2

kinoko

結果

最終結果はFailしてしまいスコア0

祈りは届かず。。。

その後

悔しい思いもありましたが、予選に比べると選抜っぽさ出せてたということで気を取り直して懇親会を楽しませていただきました

反省点など

  • 作業分担をきちんとできたのはよかったが、振り返ると自分のやった作業が思った以上に少ない
  • access_logの解析はレスポンスタイム順だけでなく、アクセス回数順のものをきちんと分析すべきだった
  • 11/14追記
    と書いたらその後すぐに@tkuchikiがgistに追加してくれました。
    ありがとうございます!
    apacheのリクエストカウント取得方法はこちら
    nginxのリクエストカウント取得方法はこちら

  • 本番は焦るけど落ち着いて対応することが必要
  • 祈りも大切だけど実力もちゃんとつけないといけない
  • ISUCON翌日に筋肉痛になったので、ISUCONに出る際は身体も鍛えておく必要がある

最後に

悔しさや反省点色々ありますが本当に濃く楽しい時間を過ごせました。

@Konboi,
@tkuchiki 一緒のチームで参加できて楽しかったです。

ありがとうございます。お疲れさまでした。