2017/10/21〜22 に開催された ISUCON7 の予選に参加して、予選突破できたので、そのときのメモです。 22日(日曜)の方に参加しました。
チーム構成
チーム名
oops
メンバー
- 2matz(インフラ、アプリ)
- nyaa(アプリ、インフラ)
- kjm(インフラ、アプリ)
今は全員同僚。
選択言語
Go言語
点数の推移
16時くらいまでは暫定一位だった。
時間 | Score |
---|---|
13:05:29 | 3,468 |
13:15:12 | 6,036 |
13:47:44 | 17,721 |
13:53:41 | 19,535 |
14:00:59 | 1,733 |
14:02:11 | 27,345 |
14:18:39 | 19,320 |
14:29:11 | 26,212 |
14:30:58 | 82,260 |
14:32:33 | 85,310 |
14:49:54 | 36,704 |
14:52:45 | 27,995 |
15:18:13 | 100,117 |
15:22:43 | 69,093 |
15:29:11 | 31,157 |
15:38:11 | 65,097 |
15:39:40 | 68,131 |
15:42:03 | 106,396 |
15:48:01 | 98,140 |
16:03:03 | 85,097 |
16:08:42 | 142,119 |
16:18:00 | 30,340 |
16:22:39 | 57,593 |
16:26:21 | 44,667 |
16:30:43 | 38,876 |
16:32:31 | 67,046 |
16:37:13 | 37,649 |
16:42:17 | 46,491 |
16:45:52 | 32,706 |
17:01:03 | 91,630 |
17:04:12 | 58,803 |
17:17:53 | 70,538 |
17:22:52 | 30,633 |
17:25:25 | 43,560 |
17:31:02 | 69,867 |
17:50:31 | 162,094 |
18:00:43 | 127,168 |
18:02:54 | 127,999 |
18:04:09 | 109,519 |
18:12:04 | 123,991 |
18:17:29 | 63,554 |
18:20:45 | 48,520 |
18:23:24 | 181,188 |
18:27:27 | 158,768 |
18:39:22 | 163,762 |
18:45:01 | 189,698 |
19:08:04 | 98,758 |
19:09:15 | 70,864 |
19:12:53 | 69,786 |
19:15:39 | 69,863 |
19:26:00 | 208746 |
19:38:05 | 215,780 |
19:56:24 | 184,449 |
20:03:47 | 202,946 |
20:08:39 | 175,430 |
20:13:03 | 161,017 |
20:15:08 | 174,941 |
20:29:59 | 146,447 |
20:31:13 | 217,747 |
20:35:43 | 199,209 |
20:38:50 | 183,515 |
20:40:36 | 146,219 |
20:43:27 | 179,772 |
20:46:04 | 185,481 |
20:49:13 | 215,451 |
20:50:39 | 195,725 |
20:51:47 | 167,884 |
20:53:04 | 216,923 |
- Best 217,747
- Last 216,923
結果
両日3チームを除いた上位12チームにおいて、8番目(全体で14位)でなんとかギリギリ本戦出場権を得られました。 ISUCON4 以来の2回目です。 ちなみに ISUCON4 のときも総合トップ13枠で8位だった。
使用したツール
- kataribe
- matsuu++
- tcpdump
- Wireshark
- goreplay
- 今回は複数台サーバがあったのであまり使わなかったが、ローカルでリクエストをリプレイしてアプリの挙動に問題ないか確認に使おうと思っていた。
- netdata
- NewRelic
- Go のライブラリだとあまり意味がなかった
- Runtime GC のところだけチラっと見たくらい
- BitBucket
- ansible
- mosh
- Dropbox Paper
やったこと
前日まで
- Dropbox Paper で当日のスケジュールをおおまかに決め共有
- Pixiv ISUCON で勉強
- 当日のお昼ご飯
- 事前に出前を予約。
当日
序盤
- 初期セットアップ
- ソースコードを git にぶっこんでサーバで git pull が行えるようにする
- ツールのインストールやSSH鍵を登録する Ansible Playbook をサーバに展開、適用
- fail2ban 無効化
- 事前に Ubuntu を試したときにハマったメンバーがいたので。
- 画像のスタティックファイル化
- nyaa がさくっと実装
- pixxiv-isucon 予習の成果
- nginx の設定をチューニング1
- Expires, Cache-Control ヘッダまわりを追加
- ETag 無効化
- これも nyaa がさくっと設定
- pixxiv-isucon 予習の成果
- message テーブルにインデックスを張る
ALTER TABLE message ADD INDEX(channel_id);
- これも nyaa
- /message のチューニング
- N+1 を改善
- これも nyaa
- /fetch のチューニング
- 私が担当したが N+1 のクエリの排除までいけず。
- haveread を Redis 化した方が良いよなーとつぶやいてたけど、結局実行せず。
- nyaa にバトンタッチして改善
- time.Sleep を消したりもしてみたが、リクエスト数が増えるだけで効果がないので戻した
- このあたりのベストスコアが142,119点だったけど、なかなか安定せず
中盤
- message テーブルにさらにインデックスを追加
ALTER TABLE message ADD INDEX(user_id);
- 最終的に
ALTER TABLE message ADD INDEX(channel_id, user_id);
というインデックスに集約。
- 複数台構成への変更
- いくつか案が出た
- 没案としては NFS や WebDav など。
- NFS は再起動時に刺さりそうだったのでやめた
- /icons 以下を3台のサーバに分散配置し、ローカルにない場合は存在するノードにリダイレクトするような処理を2matzが実装
- 残念ながらベンチマーカーがリダイレクトしてくれなかったのでロールバック
- nginx のみで複数台構成への切り替え
- 私が担当した。
- 上で書いた分散配置の施策は変更が大きくなりそうだったため、予備の案を考えておいた
- いくつか案が出た
app1, app2
server {
location /icons/ {
proxy_pass http://app3;
}
location / {
proxy_pass http://127.0.0.1:5000;
}
}
app3
upstream backend {
server app1:5000;
server app2:5000;
}
server {
location /icons/ {
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
expires max;
etag off;
}
location /profile {
proxy_pass http://127.0.0.1:5000;
}
location / {
proxy_pass http://backend;
}
}
終盤
- app1, app2 に proxy_cache の設定を追加
- /history を改善
- サーバの再起動テスト
- 1台ずつ再起動し無事起動してくることを祈る
- 各種ログの停止
- MySQL のチューニング
innodb_doublewrite = 0
innodb_flush_log_at_trx_commit = 2
- ベンチガチャ
- Goのアプリのメモリが肥大化するので、ベンチのたびに再起動させたり。
- ベストスコアに近い値を出すまで繰替えしベンチ
- 祈り
まとめと反省
-
だいたい nyaa の成果。
- nyaa に感謝
-
「推測するな計測しろ」の原則をあまり守れなかった
- netdata を使ってウォッチしていたが、大まかにしか見れていなかった
- ISUCON の場合 Mackerel などで見れる 1分単位のメトリクスだと粒度が粗いので netdata を入れて見るのが楽。
- ただ複数台をウォッチしにくい
- 2015年の記事で使用している PrometheusとGrafanaでダッシュボードを用意したかった
-
毎度のことながら SQL 力の不足
-
毎度のことながら コミュニケーション不足
- 前回より大分マシだった
- 座席の位置とかも重要かもしれない
-
app3 に負荷が集中する構成だったのは良くなかった
- app1, app2 だけでベンチを走らせてみればよかった
-
ベンチマーカーのエラー「too many connections」の発生条件がよくわからなかった
- 同時接続数の問題なんだろうけれど、ベンチマーカのバグなのか、仕様なのか判断がつかなかった。
10/22 18:27:20 エラーが発生したため負荷レベルを上げられませんでした。2017-10-22 18:27:19.812958767 +0900 JST m=+56.143739094 リクエストに失敗しました Post http://isubata.example.com/message: dial tcp 59.106.218.178:80: socket: too many open files (POST /message )
-
ルールを熟読しよう
- どのようなリクエストのポイントが高いのか、ルールに書かれているのならば把握して意識すべき
最後に
pixiv-isucon を作成、公開してくださった catatsuyさん、毎回大変な準備をされている運営の皆様には深く御礼申し上げます。 本戦がんばろう。