ISUCONとリアルISUCONへの備え
@kazuph
自己紹介
主に使ってるアイコン
自己紹介
- @kazuph
- 新潟出身
- YAPC/Tokyo App Aword(Unity Game)/NASA Hackathon/WebRTC Hackathon
- 最近勉強してるやつ
- Rails/Golang/iBeacon/IoT/Docker/Elasticserch/kibana/ fluentd/Norikra/capistrano
- 新規事業部に所属していて事業判断・営業・テレアポ・外注管理からAWS化まで幅広く担当していました。
自己紹介: 作成してるIoTプロダクト
今日は
- Webサービスにおける測定と改善の話
- ISUCONと某ブログサービス=リアルISUCONを戦う上で身につけた知識もあるよ
ISUCONとリアルISUCON
- ISUCON
- お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトル
ISUCONとリアルISUCON
- リアルISUCON
- (当時)6, 7年前から稼働していたB2B向けブログサービス
- 季節性のあるブログが多く、ピーク時はLA200くらいになって表示不可になることが多かった
- 僕がLA200とかはどうにかして、その後120秒とかかかる部分を先輩社員と一緒に改善したりしました
ISUCON振り返り
- 出場した時のお題
- チケット販売サイトの高速化
- 【予選】gist風アプリの高速化
- 参考
ISUCON振り返り
- ボトルネックの測定すること自体が意外に困難
- 測定自体に一定の実力が必要
- 測定後に正しく判断するのも実力が必要
- 測定を自動化するのにもry
- 時間は8時間、思ってるよりも全然ない
- 理想
- ボトルネック測定→それを解決する最低限の修正
- ひらすらそのサイクルの高速化
リアルISUCON振り返り
- 社内オンプレサーバーという制約
- AWSなど使ってなかったので、サーバーの調達すぐには困難だった
- 作業
- 基本的には上司につき調査やチューニングなどの実作業は1人で行った
- 自分の実力不足
0. ログだし
- nginx
- LTSVとかお好みで
- 基本的にはURLに対するレスポンス時間、回数
- ISUCONではstatus codeも確認した
- 自前で集計用ワンライナーなどを書く
0. ログだし
# LTSVなログ前提
LOG_BASE=/home/isucon/tmp
# stat url
URL_STAT=`cat $LOG_BASE/access.log | perl -F"\t" -anle '{($key = $F[3]) =~ s/(req:|HTTP\/1\.1)//g;$key =~ s/[0-9]//g;$key =~ s/ //g;$key =~ s/\//\//g;$c{$key}++;$t{$key}+=substr($F[8],6,5)}END{for(keys %t){print int($t{$_})." ".int($t{$_}/$c{$_}*1000)." ".$c{$_}. " $_";}}' | sort -nr | tee tmp/nginx-repo.txt.${DATE}`
echo "sum sec ave msec count URL"
echo "$URL_STAT" | while read timesum timeave count url; do
echo "$timesum $timeave $count $url"
done
0. ログだし
sum[sec] ave[msec] count URL
1128 1939 582 GET/
69 43 1598 GET/memo/
63 50 1247 GET/recent/
34 147 234 GET/mypage
2 9 234 POST/memo
1 0 1528 GET/js/jquery.min.js
1 0 1528 GET/css/bootstrap.min.css
0 3 234 POST/signin
0 2 234 POST/signout
0. ログだし
- app(sinatraやKossy)
- アプリがactionごとの時間を出してくれると嬉しいが
- CatalystはdebugモードだとActionごとの実行時間を出してくれて便利
- そうじゃない場合はTime.nowなどを仕込んで解決する
- Perlは時間測定、query周りでいいのがそろってる印象
0. ログだし
[mysqld]
slow_query_log=ON
slow_query_log_file=/tmp/mysql-slow.log
long_query_time=0 #出力する秒数, 0秒なのですべて
0. ログだし
- mysql
- スローログ
- pt-query-digestを使うと便利
- EXPLAINもしてくれる
pt-query-digest tmp/mysql-slow.log --explain h=localhost, u=isucon --database=isucon | tee tmp/ptqd.log
実行結果
0. ログだし
- ログを出すことでのパフォーマンス劣化は初期の時点では完全に誤差。おしみなく出した方がいい。
- もちろん本番では注意!
1. 底上げ
- 自分の得意な言語への変更
- 過去2回はPerl、今はRubyで検討中
- 近年はRubyの方がPerlよりも初期値が速い
- MySQLのパラメータ見直し
2. ボトルネック探し
- コマンドレベル
- w ← (僕は重いサーバーに入ったらまず打ちます, uptimeでもいいですがそもそも長いコマンドは重いサーバーでは打てない…)
- htop/top
- dstat -v (vmstat)
- IOならiotopが便利
3. 可視化・自動化
- この辺はできたらいいなぁって話
- ベンチマーク中に影響を与えないようにする
- ログはfluentdでバッチ転送
- 転送後は何世代か残して消す(容量がすぐなくなる)
- クライアントはGoogleSpreadsheetがいいかなと思ってる笑
- capでベンチマークから自動実行
3. 可視化・自動化
- NewRelicもいいよ!
- できれば導入したいやつ
4. 禁断のパワーに挑戦したい
- handlersocket!!!
- INSERT部分がボトルネックになったときに導入したい!
- nginx_lua!!!
- appに行ったら負けかな!?
- 直接mysql・redisなどのデータを返却する
- golang!!!
- etc…