ISUCON11予選 反省会
ISUCON11に初参加して、予選敗退しました。
悔しさを糧に来年も頑張りたいですが、まずは鉄を熱いうちに打っておきます。
また、ここでの反省は”チームとして”ではなく、”個人的に”という話です。
上手く出来た事
自分用memo-isuconを作成した
練習では、catatsuyさんのmemo_isuconリポジトリを見て作業をしていました。
このREADMEに書かれている事をファイルに書き出して、自分にとって欲しいものへの検索がすぐに行えるようにしました。
また、アプリケーション名などを変数に置き換えて、エディタで一気に書き換えがおこなえるようになっています。
サンプル
# Database: {isucon_db}
# バックアップ
mysqldump -uroot {isucon_db} > dump.sql
# 戻す時
mysql -uroot {isucon_db} < dump.sql
結果、練習よりもスムーズに行えた気がします(体感値)
データベースのGUIクライアントツールを用意していた
これは、たまたま容易していただけなのですが、DBを俯瞰的に眺める時はGUIで操作できるアプリケーションがあるととても助かります。
おすすめDBクライアントツールはTablePlusです。
出来たけど無駄に時間かかった事
DBから画像の抽出に手間取った
今回、isuテーブルのimageカラムに画像がblob型で入っていました。これを抽出してバイナリファイルとして書き出すだけの事ですが、無駄に時間が掛かりました。
まず前提として、ISUCONはGo言語で参加しました。しかし自分はGo言語とはフレンドリーな関係ではないので、チームに影響が出ないところはPythonで書くことにしました。
PythonでDBを操作すること自体はやったことがあるし、やり方もイメージ出来ていたので楽勝だと思っていたのですが、今使っているPCの環境にMySQL操作系のライブラリが入っておらず、それを探すところからはじめました。
Python3.7で動きそうなPyMySQL
をインストールしました。
$ pip install PyMySQL # インストールは成功していた
$ python -m "import PyMySQL"
[path-to]/bin/python: No module named import PyMySQL
なんで???
予想ではpyenvとpipが上手く紐付いていない気がして、闇が深そうなので諦めました。
次に、Goのアプリケーション内にGETアクセスで全ての画像の書き出しが出来るAPIを立てようとしました。しかし、Goでの書き方がわからない事が多く、やり方がイメージ出来なかったので諦めました。
最終的にDBクライアントツールのエクスポート機能からCSVに書き出しました。PythonでそのCSVをパースしてバイナリファイルとして保存しました。MySQLとの接続を考慮する必要が無くなったので、標準ライブラリだけで何とか出来ました。(実際はpandas.read_csv
使いました)
※追記
今見たらPython実装のディレクトリにrequirementsがありましたね。。
SSHの接続にあたふたした
本番ではGitHubで使っている公開鍵がサーバーに登録されていました。これは練習で使っていた公開鍵ではありませんでした。.ssh/config
はチーム共通で使っていたので、Permission denied (publickey)
となりました。
結局、共有した.ssh/config
から各サーバーのIdentityFileを書き換えました。
秘密鍵はどれがどのサービスで使っているか、ひと目でわかるようにしましょう。
やったけど出来ていなかった事
デプロイスクリプトが間違っていた
init.sh
でテーブル全てを作り変えており、POST /initialize
で必ず呼ばれていたので、サーバへのデプロイはビルドしたGoアプリケーションとsqlファイル(ここにインデックスを貼る処理を書いていた)をアップロードする必要があります。
webapp/sql/
配下は全てrsyncしていましたが、rsync先を間違えていました。
rsync -vau ../sql/ $server:/home/isucon/isucondition/webapp/sql/
正しくは
rsync -vau ../sql/ $server:/home/isucon/webapp/sql/
でした。
単に注意不足でしたが、デプロイスクリプトの不具合はチーム全体に迷惑をかけてしまっているので猛省です。
.ssh/config
の設定が間違っていた
共通のデプロイスクリプトの都合上、チーム全員が共通のホスト名を使うようにし、そのために共通の.ssh/config
を使うようにしていました。
それを作る担当が僕だったのですが、ssh/configの書き方をよく理解せず、memo_isuconの.ssh/configをコピペしていたので、ProxyCommandをつけていました。
Host isu01
HostName xxxxxxxxxxxx
User isucon
Port 22
IdentityFile ~/.ssh/id_rsa.github
ForwardAgent yes
Host isu02
HostName xxxxxxxxxxxx
User isucon
Port 22
ProxyCommand ssh isu01 nc %h %p
ForwardAgent yes
isu02はisu01を踏み台にする必要はないし、そうすると逆に接続できなかったりするので、ProxyCommandは完全に不要です。
自分以外のチームメンバーはゴリゴリにインフラやっている人なので、ミスは1回のエラーで瞬殺だったのですが、このような基礎的な事が出来なかったのは猛省です。
やり始めたけど出来なかった事
Go言語でインメモリキャッシュ
画像をファイルに書き出したら、それ以外のisuテーブルのデータをインメモリにキャッシュできそうだったので、やってみました。が、出来ませんでした。
前述のとおり、自分はGoで書かれたコードを読む事が得意ではないので、どうやって実装に組み込めばいいかわかりませんでした。
Nginxでtry_filesの設定
今回は画像にユーザーのログイン認証が必要だったのですが、アプリケーションで画像を返している部分をNginxで返すことで高速するTipsは、過去のISUCONで何回かありました。
つまり、「画像をNginxで返すようにしましょう」って方針になったら、出来る事が当たり前に期待されるのですが、出来ませんでした。
具体的には、URIが/api/isu/:jia_isu_uuid/icon
となる時に/home/isucon/webapp/public/img/:jia_isu_uuid
を開くようにしたかったのですが、わかりませんでした。練習不足です。
まとめ
上記の反省点は、天才的な閃きが必要だったり、圧倒的に技術力が足りないことではなく、単に練習不足です。
また来年、がんばります。
リンク集
予選で使ったリポジトリ
チーム全体として何をしたか(出来なかったか)などのまとめ。catatsuyさんの感想など。
Discussion