ISUCONに参加してきた
まずは運営のライブドアの皆さま、楽しいイベントをありがとうございました。
さて、俺id:inuzことTwitterID: inuwarumonoは同じ会社のアプリ屋2名と一緒に、チーム名「ツヤマ倶楽部」として出場してきたのでそのメモ/レポートを。
出場者3名とも名前はツヤマさんでは全然なくて、ツヤマというのは弊社技術部門の最高責任者の名前。(会社名は非公開)。
俺はインフラ/ミドルウェア屋なので、主にOSやらミドルウェアの最適化を考える担当。あとの2名はアプリケーション側からの切り口での改善と、それに伴うミドルウェアの最適化。両面からのアプローチというのが当初の作戦だった。
事前準備が肝、ということでツヤマ倶楽部の面々が考えていた事前対策は以下のとおり。
- DBのクエリ解析が肝になるはず。的確にボトルネックを探すには断然クエリアナライザ。
- パフォーマンスモニタリングが重要、でもまぁsarで良いか
- OSのメモリパラメタチューニング練習しとこう
- WebサービスってインフラチューニングよりよっぽどHTML最適化のほうが高速になるよね
- あとはアプリを見ないと何とも言えないね
みたいな感じ。結果から言えば大げさだったり、的外れだったり。それぞれの考察を軸に当日を振り返りたい。
クエリ解析について
当日もらったアプリは想像をはるかに超えた単純さだった。もっと大規模なアプリケーションが相手だと思っていた。想像の10分の1以下のシンプルさで、これにはとても驚かされた。
大規模環境を想像していたツヤマ倶楽部の面々が何を用意したかというと、クエリの頻度・クエリごとの実行時間など、クエリの種類ごとの情報が詳細に把握できるように、MySQLのクエリアナライザ。なんと有償ツール、のトライアル版。これでどんなSQLが来ても完璧にチューニング対象を特定できる!と思って用意していたのだ。
MySQLのクエリアナライザを使ってみた感覚としては「マジ使える」「すげぇ欲しい」。
アプリとDBの間にMySQL Proxyを挟んでクエリを盗む形で組み込むのだけど、これがもう涙ものの使いやすさなので、詳細は http://www-jp.mysql.com/products/enterprise/query.html ここでも見てもらいたい。MySQLサーバの負荷で悩む御仁にはぜひ一度は試してもらいたい。
当日の話に戻すと、このクエリアナライザのセットアップを始めてすぐの時点で、さらっとアプリを読んだだけで、サイドバーのクエリがボトルネックであることはわかってしまった。ちょっと見ればわかるレベルで明らかだった。超優秀有償クエリアナライザ意味なし状態。
超優秀有償クエリアナライザは、数値的裏付けで最新コメントクエリの遅さを示してくれただけだったけど(数字忘れたけど95%以上の負荷がアレだった)、僕らにとってのメリットはこのツールが超優秀で超使えることがわかったこと。本当にオススメです。有償だけど、これはその価値を認めざるをえない(値段は知らんが)。
ちなみにMySQL Proxyとluaスクリプトを組み合わせて解析ツールを自作出来そうな気がするのだけど、プレースホルダを使ったクエリでうまくデータが取れないなど、事前検証をしたメンバによると、はまりどころがあったそう(時間がかけられず解決はしていないらしい)。
パフォーマンスモニタリング
とりあえずもらった4台すべてで yum install sysstat した。パフォーマンス記録の基礎中の基礎。/etc/cron.d/sysstat をいじって5秒ごと取得に変えた。並行して、手元の画面では vmstat 1 して眺めた。
けっこうみんなtopを使っていたようだけど、俺はvmstatのほうが好きだ。理由は何だろう?履歴が同じ画面に残るからかな?あと、cs を眺めることが多いかもしれない。cs=コンテキストスイッチがやたらと発生するシステムはCPUネックになっている事が多い。このシステムなら普段からcsこんぐらい発生してるしな、みたいな感覚値っていうのかしら。運用者の慣れのようなものがvmstatにはある気がする(俺の場合だけか)。俺がtopをあまり使わないのは、どのプロセスが重いかなんて、1サーバあたり1ワークロードで作ってる限り自明すぎて情報にならないから?とか想像する。ターミナルの行数を下回る程度で複数のプロセスが回るシステムや、CGIみたいにプロセスがぽこぽこforkされるシステムなら使う、そんな感じか。
OSパラメタチューニング
高速なシステムを作ろうと思ったら、ディスクI/Oを発生させたら負け、これはもう全チームが当たり前に持っているセオリーだろう。そんでもって、みんなmemcachedとかメモリキャッシュ機構を実装するんだろうなと思った。
当たり前のことをやってみんなと同じになってもつまらないと思い、以下のような事を考えていたが、これは現場では採用しなかった。
- LinuxのファイルシステムIOに極端なwriteバッファと遅延書き込みを設定
- 突然死すると当然のごとくデータロストになる(のでサービス環境では絶対ありえない設定)
- OS領域とアプリ領域が別ファイルシステムなら気兼ねなく設定やりなおし可能だな
要するに、アプリケーションがファイルに読み書きしているつもりのファイルシステムIOを、LinuxのVFSレイヤでメモリにのっけちゃおう!というアイディア。ファイルシステムのマウントをwritebackに設定して、/proc/sys/vm以下のページキャッシュに関するパラメタを変更しまくれば良い。
採用しなかった理由は簡単で
- やっぱりOSもアプリも同じファイルシステムだった
- Dom0からの支援が得られない以上、面白くてトリッキーなだけでメリットの少ない実装は選択できない(writeback設定ミスで再起動不能だとツラすぎる)
こんな感じかしら。インフラ屋的に面白いだけで、isuconの趣旨と離れるしね。(突然死=データロストは、"いいかんじ"ではない)
あとは、ハードウェアはきっと Xeon 5600番台の64bitだろうから、Kernelイメージ作って持ってく?とか言ってたけど、やっぱりDom0操作がない環境で実行するにはリスクを感じたので、渡されたKernelそのままを使った。
HTMLチューニング
先に書いた大規模なシステムを想像していた、というのは要するにLivedoorブログほとんどそのままみたいなアプリを想像していたということ。そして計測ツールは、ブラウザのような動作をするツールなんじゃないかという想像もあった。
結果この想像はどちらも間違っていたのだけど(実際に運営側になったつもりで想像していたらそれがほとんど不可能な事は想像できたはずなのだけど)、通常のWebサイトへのアクセスを高速化しようと考える場合、サーバやアプリの改善よりじつはよっぽどHTMLの改善のほうが「効く」んだ。
Yslowみたいなツールを使って「サイト高速化」を検討した事がある人にはわかると思うけれど、HTMLを改善すると下手なサイトなら、一ページあたりのHTTPリクエスト数を半数以下にできたりする。この時、単純計算にせよサーバ負荷は半分になるから、HTMLの改善がどれだけ効果が高いかわかって頂けると思う。そして、これをisuconでもやってやろうと思っていた。
レギュレーションには「Dom構造を変えず」とか「見た目が変わらなければ」とか、HTMLに関する内容も含まれていたから、渡されたアプリがCSS/JSファイルだけで30個、画像ファイルが50個あるようなサイトだったらアプリなんてほっといてHTML改善だけで一位になれるな、なんて思っていたわけだ。
ここでも俺の想像は大外れをしていて、目論見はまったくハズレてしまった。md5値を取られたんじゃ1バイトも変更できない。
実際にアプリを見て
なんでか俺は勝手に、CGIを前提にしたPerlスクリプトが渡されるんだと思っていた。mod_perlとかfast_cgiに載せるところから始めることになるだろうな、という想像をしてたから、本当に面喰った。
Perlのアプリケーションサーバなんていう実装をロクに知らず、Starmanは初見どころか俺は名前すら知らなかった。
スレッドを増やす方法もわからないし、純粋にアプリ負荷なのか、Starmanのオーバヘッドなのか、Starmanのセッションハンドリング性能ってどうなの?とか、知らないことだらけ。サイドバーによるDB負荷は早々に解消してアプリケーションサーバ負荷にボトルネックはシフトしていたから、Starmanについて知らなすぎる状況には少し冷や汗が出た。
そこで、俺は知らないアプリケーションサーバを勉強する時間惜しんで、Apache + mod_psgi にすることにした。PSGIの存在ぐらいは知ってたので、こう決めてしまうまでは早かったと思う。
mod_psgi自体のインストールはさっくりと終了。Apache + mod_psgi では FindBin が動かなくなったので、フルパスをベタ書きに変えた。そんだけでアプリは動いてくれた。ここまでは簡単だったけど、リクエストをぶんぶん回していると、急に500エラーが返るように。原因はDBIのSegmentation faultで、これにはお手上げ。mod_psgiとの相性なのか何なのか、ここに時間を使ってしまったのは間違ってたと今なら思う。結局Starmanに戻すしかなかった。
あとはフロントのApacheを自前コンパイルのApache2.2(moduleそぎ落とし版;mpm=worker)に置き換えてnginxと遜色ない感じにして(ほんとだよ)、接続数パラメタをいじったり、MySQLのメモリチューニングと起動プロセス数をいじったり、いろいろやったけど、思うような結果に導けなかった。
思うような結果が得られなかった理由はkeep-aliveで、ここに気付かなかったから。kazeburoさんあんた鬼だよ。脱帽です。参りました。
ツヤマ倶楽部はボトルネックが見つからないと悩み、的外れなチューニングに終始したために、上位陣に大きく水をあけられたまま終わったので、そりゃ悔しいよ。
その他
DBネックがアプリネックに移らない場合には、DBのレプリをやろうと思っていた。アプリサーバとレプリサーバを同居。DBにもアプリを設置。リバースプロキシでPOSTリクエストが来たらDBに投げて書き込み、その他はアプリサーバに投げる構成。
アプリ+レプリ子をUNIXソケットで繋ぐとメリットありそうだったし、リバースプロキシが更新リクエストと参照リクエストを分解する構成って面白いなーって思った。memcachedを置くならリバースプロキシで。
DBネックがすぐにアプリサーバに移ったからこれはやらなかったけど、アイディアとしては嫌いじゃない。
実際の仕事の場だと、アプリがクソでも修正できない場合があったりして、ミドルウェア以下でなんとかする場面があるので、俺の脳みそはアプリをいじらずに高速化するには、みたいな思考が染みついているらしい。ここに気付いたのも個人的には収穫。
最後に
ログ吐くのもやめちゃおうぜ、とか力石みたいなチューニングも議論してたけど、その段階に達する前にボトルネックに気付けなかったし、時間足りなかったし、時間ができたら復習しようかと思っている。
懇親会の後手を挙げて「俺インフラ屋だから、次はウチでやる」って言ったのは俺なんだけど、酒の席の戯言だと思って流してもらえると嬉しい。上司には話してみるけど期待はしないでね。準備を想像するに、課題作るだけでも大変なことだよこれは。正直あれを作り上げられるだけのメンツはなかなかいませんよ。
ほんと運営の皆さま御苦労さまでした。社内にも最初はまじでー?みたいな声があったみたいだけど、ここまでの完成度に持ってこれるライブドアの技術部隊は素晴らしいです。今の仕事がつまらなかったら転職考えたいレベル。
参加者のみなさんもお疲れさまでした。面白かったね。