ISUCON7の予選で敗退した
Blogにまとめるまでが、ISUCON
と、言うことで久しぶりにこっちに書く。
前から興味はあったけれど、参加者のブログを見る程度だった。
そんな時に、会社の同期に誘ってもらったので、ホイホイ受けてみた。
事前準備
過去問がVagrantで公開されているので、本番と同じ10:00-18:00でISUCON6の問題を解いてみる、ISUCON5の問題をざっくり読んで改善点を挙げる、というゆるふわな対策を行った。GitHub Privateにリポジトリを用意したり、Google DocにTODOリストを作成したりと、ここまでは良い感じだった。
自分の担当はDeploymentだったので、AnsibleのPlaybookをちょこちょこ作っていた。最近は専らDockerfileを書いているので、すっかり使い方を忘れていたけれど、Best Practices — Ansible Documentation 見ながらなんとなく書けるので、Ansible楽で良い。
Host Machine -> Vagrantで立ち上げたisucon5用のVM にansible-playbookするためのinventory fileはこんな感じ。
当日
開始直後
いきなりインスタンスが3台あってちょっと焦る。
とりあえず、Ansible script流す。InventoryにIP Address追加するだけだから、流す分には特に困らなかった。なお、各自のssh keyは ssh-copy-id で送れというスパルタ仕様。
そして、ベンチ走らせてみる、確かデフォルトがPythonで1台にだけ負荷をかけた状態。
Time 2017-10-22 13:27:06 +0900 JST Message ok Score 2282 Best 2282 LoadLevel 1
Goに切り替える。やっぱり1台だけ。
Time 2017-10-22 13:32:00 +0900 JST Message ok Score 4521 Best 4521 LoadLevel 1
2台だと?
Time 2017-10-22 13:35:38 +0900 JST Message ok Score 5030 Best 5030 LoadLevel 1
あんまり増えないね。
ということで、コードリーディングタイム。
14過ぎ辺り
改善できそうな所を出し合う。
alp用のログフォーマットをNginxに適応して、実際のデータを確認。これは、最初にやっても良かったかも。あと、access_log /var/log/nginx/access.log ltsv;
パスの後ろにltsvをつけ忘れるという凡ミスを犯した、ごめん。
DBのチューニングや、index効いてない、N+1問題などベタな所を修正。
iconの画像を、毎回DBから取得しているのが遅いよね。ということで、静的ファイルに書き出してNginxから返そうという方針に。
16時過ぎ辺り
新規、更新のiconはファイルに吐けるようになったので、既存の画像もファイルにしてしまおう。
Time 2017-10-22 16:43:26 +0900 JST Message 負荷走行前のバリデーションに失敗しました。2017-10-22 16:43:25.201090568 +0900 JST m=+1.524851228 [Fatal]画像データが正しくありません (GET /icons/65ea5a70b1fcf8f5f816b01b87f2aca2251315b0.png ) Score 0 Best 7225 LoadLevel 0
謎のバリデーションエラーにより、Nginxから返す作戦を諦めアプリから返すように戻す。
しかし依然として出続けるバリデーションエラー。。。
この時は、変更を1号機にしか適応していなかったので、2号機に1号機のバイナリを持って行って再現確認。結果、再現せず。
ベンチマークツールに変なファイルキャッシュされたのか?と散々悩む。
18時過ぎ
ダメだ、バリデーションエラーが出続ける。もう、諦めてラーメンか?という思いの中、DBのデータから静的ファイルを生成するロジックを書き換えたら、バリデーションに通った!危うく、ISUCONに出たこと自体を無かったことにするとこだった。
Time 2017-10-22 18:21:50 +0900 JST Message ok Score 23513 Best 23513 LoadLevel 1
その後、iconはinitializeの時にNginxのメモリに載せたいよね。という話になるが
で、どう設定すれば良いの?
という残念な状態になり、必死にググるおっさんたち。
20時過ぎ
せめて、アプリを3台にスケールしようということで、2号機とDB用だった3号機にもアプリを展開。
Nginxのログを切って、MySQLのSlow Queryログも切って、できる限りのことをした結果。
Time 2017-10-22 20:50:48 +0900 JST Message ok Score 42731 Best 44732 LoadLevel 1
4万ちょいでフィニッシュでした。
総評
Ansibleでスマートにデプロイしたかったけれど、makeが通らない!等焦ってしまい、書き捨てのShellで凌いだのが負けた気分だったし、そもそもデプロイするところまで事前に用意しておくべきだった。
ETC_BR=${1:-master} APP_BR=${2:-master} cd /etc.git sudo git fetch echo "[INFO] Checkout $ETC_BR" sudo git checkout $ETC_BR sudo git pull sudo cp -r /etc.git/nginx/* /etc/nginx echo "[INFO] Restart Nginx" sudo systemctl restart nginx cd /home/isucon/isubata/webapp/go git fetch echo "[INFO] Checkout $APP_BR" git checkout $APP_BR git pull make echo "[INFO] Restart Go APP" sudo systemctl restart isubata.golang.service
あと、過去何度もNginxが登場しているというのに、Nginxへの理解が低すぎたのは大変よろしくなかった。
とても悔しかったので、来年リベンジしたいな。