大森s ISUCON5 初参加6位でした
毎年TLから見学していたISUCON、今年は社内メンバーの勧誘に成功したので初参加しました。
メンバーは みね, @yukiex, @shun0922 の3名で参加してきました。チーム名は会社の所在地ということで 大森s に。
本戦も予選も役割分担はだいたい以下のような感じで、お互いの領域を少しずつカバーしながら作業しました。
当日の朝
今は横浜ですが、東京在住の頃から渋谷は怖くてあまり近づかなかったので迷うかと思って早めに出発。
9時頃には11Fに到着し、先に到着していたのは2組程度でした。
個室ゲットできるといいなと思っていたら、メンバーが乗車している電車で人身事故が発生したと連絡。
到着が遅れチーム全員揃わないと入れないバリアに阻まれ立ち往生。それでも10時前には入場できました。
普段 MBA 11' に外部モニタという構成なので、モニタのかわりに MBA 13' を追加で用意したり、メンバーのために燃料(カフェオレ)を用意したりと、バッグがいい感じの重量(20kg程度)になってました。
開始直後
配布された封筒からホストとIPがわかった時点で開発機などに hosts ファイルを配置しメンバーに共有。
開始と同時にキューを入れ、それが記念すべきISUCON5Fの初キューだったらしくスコア1064で1位!
レポジトリにソースを取り込み App をのぞきはじめたメンバーからAirbnbを3行で説明しろと言われたので、
一般人が
一般人を
泊めるサービス
と説明。「えっ?ホームステイ的な!?」となっていたので「空き部屋に」を補足。
こちらではまず OS が Ubuntu 14.04.3 なことを確認。
Chef のレシピが適切なものを準備出来ていないため iTerm2 の Broadcast Input と、pssh を駆使して3サーバの環境を同時に修正。
hosts, shell, key 修正 (isucon, root ユーザ)、dstat, htop, zsh などを入れる。
ミドルウェア周りはDBサーバが psql (PostgreSQL) 9.4.5 で nginx が 1.4 なことを確認。この辺で15分経過。
メンバー2名はここ数ヶ月 PostgreSQL と過ごしてきたので小さくガッツポーズする。
App 担当は PostgreSQL の経験がほとんどなく、さらに開発環境が Mac じゃない上に VM 環境もないということで手元に開発環境が構築できないため、VPN越しに社内に環境を作る。しかし直接API接続できないということで諦めて c サーバに居を移す。
vim の設定やら ag もいれつつ、スーパーバイザーを探して perl に変更、自動起動などを変更する。
そして nginx に worker 数、静的コンテンツ配信と UNIX domain socket の設定、supervisor 側に Gazelle の設定など、同時に変更するもなぜか nginx の configtest で fail する。
なんとか設定変更を最小限にとどめ、とりあえず nginx start する。
午後
となりでDB担当が pgBadger を使って slow query をまとめてくれたので眺めてみるも、あまり最適化の余地がない。この辺で12時15分頃。
App 側で JSON モジュールを JSON::XS に変更。
アクセスログも alp で集計して眺めながら 外部API 呼び出しをなんとかしないと、他にはあまり余地が無いという話になる。
気休め程度に endpoints をコードにインプリメントする。スコア2781。
13時30分頃、Redis でキャッシュする方針で、サーバインストールと設定、Perl設定、App実装とそれぞれが実施。
ついでに前回調査時に Furl より Net::Curl のほうがベンチ結果が良かったということで Net::Curl も cpanfile に仕込む。
Redis の実装が完成する前に API とのやり取りを確認したかったということもあり Varnish をプロクシとしていれるように作業。エンドポイントをバックエンドにマッピングしてひとまず動作する。
13時45分頃、DBにインデックス create index users_email on users (email, passhash)
を追加し少しスコアあがる。
Net::Curl で Last-Modified 対応と、Accept-Encoding 模索するが、Redis 待ちで一旦放置する。
14時30分頃、Redisの実装が完了、5000〜6000程度までスコアが上がる。
後半残り3時間
そして運命の15時15分から数分前、再度 nginx の設定を変更していてやっぱりおかしい。作ったはずのソケットがない。
あ、俺 supervisorctl reload
するの忘れてるやん!!と自分の凡ミスにいまさら気づく
15時15分頃、やっとワーカーが増え Gazelle と UNIX domain socket の導入ができたのでベンチする。スコア 30807 。ワーカー数を倍にして 61552 、更に調整して 65295 に落ち着く
その間、App 側は着々とキャッシュの実装を追加し Expire の個別対応、token_key の設定などを実施。
15時45分頃、そろそろ複数サーバで負荷分散できるようにしたいということで、2台で調整を開始。
/initialize
の初期化対象DBホストがローカルだったのを見落としていて少しハマる。
redis の bind など変更してテスト、Varnishも外す。
DB担当は pgpool-II を入れるかどうかでやきもきしていたようです。
2台の構成
isu08a DB, App isu08b LB, Redis, App isu08b (nginx) -> (App) -> (nginx) -> (App)
上記のように nginx to nginx の若干、変則的な設定を実施。
16時30分ごろ、スコアは 69880 となり3位になったので reboot テストなどを実施する。
残り1時間
17時10分頃、userjs のレンダリングをやめて直接生成に変更。スコアを 83776 まで上げ3位を維持。
たまに fail するので Tenki API のキャッシュ保持をいつまでするかを調整開始
また reboot 直後に fail することがあり、PostgreSQL で App が DB 接続した後に DB が落ちると接続がロストすることを思い出す。念のため env.sh に sleep を仕込む。
17時30分頃、サーバを3台体制に変更しベンチを実施。スコア 90120 とチームとしては今大会の最高スコアを記録。
17時40分頃、fail 対策で Tenki APIのレスポンス日時からキャッシュ時間を調整するように変更。
全サーバ reboot テスト。スコア 84983 にダウン。
17時50分頃、更にTenki APIのキャッシュタイムを5分から60秒に変更。
結果
17時56分の段階で best score で5位、上位陣の fail などでなんとか入賞に望みをかけましたが結果6位でした。
後になってみると、ツメが甘い上に対応も甘く反省しかない結果でした。
なにより上位陣がしっかり着手していた、並列リクエストができていなかった点は痛かった。
データのシリアライズに関しても MessagePack やもっと効率のいい方法を使うべきだったし。
gzip_static などもヘッダをしっかり読み、基本に忠実であればできたはずでした。
非常に悔いが残りましたが、自分たち(主に自分の)未熟さがそのままスコアに反映された結果なため満足です。
来年までにクソ精進する。
最後に、941 さん、tagomoris さん、kamipo さんをはじめ運営・出題チーム、スポンサーの皆様、本当にありがとうございました。
非常に楽しかったです。
Score History
timestamp | score | note |
---|---|---|
11:01:58 | 1064 | |
11:50:04 | 1029 | |
12:01:42 | 0 | FAIL: |
12:27:59 | 0 | FAIL: |
12:35:06 | 0 | FAIL: |
12:55:24 | 968 | |
13:10:44 | 1012 | |
13:12:53 | 0 | FAIL: |
13:16:39 | 1023 | |
13:34:03 | 985 | |
13:37:21 | 0 | FAIL: |
13:40:42 | 1094 | |
13:51:48 | 2781 | |
13:52:37 | 84 | FAIL: |
13:56:43 | 84 | FAIL: |
13:59:35 | 1026 | |
14:09:01 | 2023 | |
14:09:37 | 84 | FAIL: |
14:12:26 | 1899 | |
14:14:59 | 2658 | |
14:27:46 | 5268 | |
14:29:13 | 6298 | |
14:30:44 | 5759 | |
14:32:21 | 1173 | |
14:34:25 | 971 | |
14:41:46 | 1176 | |
14:44:34 | 1097 | |
14:51:12 | 1051 | |
14:52:53 | 5481 | |
14:57:12 | 1088 | |
15:02:02 | 84 | FAIL: |
15:06:50 | 6438 | |
15:08:29 | 84 | FAIL: |
15:10:17 | 1013 | |
15:13:04 | 5624 | |
15:15:12 | 30807 | |
15:20:01 | 0 | FAIL: |
15:21:30 | 61552 | |
15:24:52 | 58009 | |
15:26:30 | 0 | FAIL: |
15:28:09 | 65295 | |
15:30:35 | 58569 | |
15:32:27 | 0 | FAIL: |
15:33:50 | 0 | FAIL: |
15:34:16 | 40 | FAIL: |
15:38:37 | 57888 | FAIL: |
15:40:19 | 71 | FAIL: |
15:42:53 | 71 | FAIL: |
15:45:29 | 55325 | |
15:57:46 | 59 | FAIL: |
15:58:29 | 59 | FAIL: |
16:01:23 | 84 | FAIL: |
16:02:15 | 84 | FAIL: |
16:03:43 | 53708 | |
16:08:34 | 84 | FAIL: |
16:11:24 | 84 | FAIL: |
16:13:41 | 84 | FAIL: |
16:17:36 | 84 | FAIL: |
16:22:53 | 73 | FAIL: |
16:24:52 | 69880 | |
16:25:27 | 84 | FAIL: |
16:28:13 | 0 | FAIL: |
16:33:58 | 67431 | FAIL: |
16:36:00 | 84 | FAIL: |
16:38:10 | 84 | FAIL: |
16:40:25 | 63105 | |
16:41:10 | 84 | FAIL: |
16:43:49 | 52687 | |
16:45:34 | 10450 | |
16:49:10 | 84 | FAIL: |
16:51:59 | 54244 | |
16:54:39 | 57995 | |
16:56:35 | 84 | FAIL: |
17:00:07 | 40 | FAIL: |
17:01:41 | 55920 | |
17:09:08 | 83776 | |
17:13:31 | 0 | FAIL: |
17:15:18 | 0 | FAIL: |
17:17:22 | 0 | FAIL: |
17:19:33 | 79152 | |
17:21:39 | 0 | FAIL: |
17:24:33 | 78635 | FAIL: |
17:27:23 | 71501 | |
17:29:49 | 90120 | |
17:33:53 | 49139 | |
17:39:38 | 84983 | |
17:42:55 | 81641 | FAIL: |
17:46:59 | 40026 | |
17:51:30 | 74185 | |
17:56:31 | 84114 |