今年も isucon に参加した。 id:tyage と id:non_117 と一緒に参加した。
max 113846、最終的なスコアは 95252 だった。言語は ruby 。今年は社会人枠で出たので本戦には10万点ぐらい足りなかった。
まあ学生の中だけで考えると上の方に位置していたので良いんでは? 前回は fail だったし大躍進である。
レポジトリはこちら。 Systemd の設定ファイルなどコミットしていないのも一部あるけど。
準備
もともと何度か出場していたので今回は特に練習は行わなかった。デプロイ用のスクリプト、負荷試験用スクリプトなどの軽い環境整備はチームの人がやってくれていた。
当日
自分は11時過ぎに起きた。一時間遅れていなかったら遅刻するところだった。
ついたあとは3人で軽く作戦会議。初動の分担を決めたりしていた。
開始
蓋を開けてみたらまさかの複数台構成だった。しかもちゃんと DB と app が分かれていて。
あとは時系列で。
- 13:00 mackerel やデプロイスクリプト、 ssh 鍵などを整備。
- 13:30 実装を眺める。nginx のログを仕込む。
- 14:00 goaccess で計測結果の確認。 今度はスローログを見始める。
- 14:30 nginx で
/js, favicon.ico, /css, /fonts
を cache で返すようにする。 - 15:00 icons のキャッシュが上手く行かなくて調べ始める。 また、スローログから index を貼ったりする。
この時、なかなか 304 が返らなくて調べていた。最終的に tcpdump
して正常時とヘッダーを見比べ、一回目のレスポンスに Last-Modified
ヘッダがないことが原因とわかった。
icons は一回置かれたら変更されないことがわかっていたので、 nginx 側で add-header Last-Modified "Sat, 04 Jun 2011 08:51:44 GMT";
と固定してしまった。これで、 304 が二回目のリクエストから適用されるようになり点数がだいぶ上がった。
次は一回目の icons 取得、その他一般の api がネックになるようになったので、アプリケーションのコード自体を変更する必要が出てきた。
- 16:30 icons 以外の遅い部分を改善し始める。 sleep はとりあえず消した。
なぜか2台目の app がうまく動かない。よく見たら python が動き続けていた!! ちゃんと disable する。
- 17:00 proxy_cache を使って nginx で img をキャッシュすることで一回目のアイコン取得の高速化を試みる。
うまくキャッシュできたが、結局 /register
で新しく登録されたアイコンを取ってくるのは遅いままなので、DB をやめてファイルに置くことを検討する。
- 18:30 リクエストはすべて一台の nginx で受けるようにして、app を分配することにする。
また、 mysql に画像を保存するのをやめてすべて LB のあるサーバーに置くようにする( /profile
もこのサーバーに飛ばす )。これで nginx から静的配信ができるようになった。この時 3~5 万ぐらい?
- 19:00 app をよく見ると N+1 がたくさんあったので改善する。サーバー側では FD 増やしたり mysql のキャッシュ増やしたりしていた。
この頃から DB のコネクションが残り続けることが問題になり始める。結局 statement をすべて close
するようにした。
- 20:00 puma のスレッドを増やしたらスコアが増えていくことに気づく。結局二台とも50スレッドぐらい動かした。11万点ぐらい取れたので満足し始める。
この辺りでやっと CPU が全部 100% 回るようになった。
自分は主に nginx・キャッシュ、その他サーバー周りを見ていた。
反省とか
- キャッシュ周りの解決に2~3時間かかっており、ここを N+1 の残りとかに回せればもう少し点取れてたかもしれない。さっさとファイルに保存するようにしておけばよかった。
- unix domain socket にしようとして失敗したのだけど、できていればファイル投稿周りは早くなっていたと思う。
- もうちょっと早くなってくると、雑な nginx LB 一台だと帯域が〜〜ってなってきそう。
結局今年は redis 一切使わなかった。 varnish とか使うと icons 周りでもうちょっと捌けたかもしれない?
log をみてちゃんとキャッシュができているか(304 が返っているか)丁寧に確認したのは良かった。ブラウザと挙動が微妙に違ったので。
- mackerel-agent を入れていたのも良かった。はじめにサーバー情報を取得できるし、どこで詰まってるかもわかりやすい。
感想
バランスが取れていて良い問題だったと思います。いろいろ改善できる場所があり、楽しくて良かった。
来年も絶対に参加したい。社会人枠でも本戦に出れるぐらいにならないとな〜。
運営の方々、今年もありがとうございました。本戦の問題も楽しみです。