in Event, ISUCON, Server

ISUCON5に参加してチームは惨敗だったけど個人的に持ち帰れたこと

すろっくさんです。

今更ですがISUCON5にチームくまさんでのびすけ氏、うめゆき氏とともに参加しました。

結論からいうと惨敗でした。今回の予選の解説はこちらで書かれているので、敗因はつかめましたので、そこを含めてかければと。

担当は僕がインフラ、のびすけ氏とうめゆき氏がアプリ・DBでした。二人にコードレベルでのチューニングとDBの精査をお願いし、僕はLinuxカーネル〜ミドルウェアを担当しました。

悲劇はすでに開始前に起きていて、node.jsでいこうぜ!って話していたのにnode.jsが廃止になったんですよね。でも個人的にはこれは直接の敗因ではないのかな、と感じてます。

要素の一つとして、アプリを見てもらった二人に残された言語が不慣れなものしかなかったことが一つ。PHPをあまり業務で触ってなかったとのことなので、すごくすごくやってて辛かったと思います。本当に申し訳ないことをしました。今回の出題はDBまわりを改善することで大きくスコアアップを見込めたようなので、そこまで到達する前にタイムアップ、という感じでした。

でもその一方で、僕はインフラのチューニングをごりごりとやってて「どうしてPHPの速度こんなに上がってるのにスコアあがらないんだろう」とか「WEBの速度あがってるのにスコアあがらないんだろう」とかいろいろ考えていました。

そんな作業の中でやってて得たものを共有します。これについてはすごく有意義だった。

HHVMの速さ素敵だった

以前はインストールに、起動にめちゃくちゃ面倒だったHipHopVMですが、今回久々に入れてみたところすんなりインストールでき、チューニングをある程度したところPHPの実行速度がphp-fpmを使用していた時と比べて10倍〜17倍くらいになりました。これはやばい。

HHVMはみんな大好きFacebookが開発したPHP実行環境です。WIKIMEDIAさんのブログに書いてある詳細によるとコードの実行は以下のような特徴があるようです。

HHVMはまだPHPインタプリタの役割を果たし、事前のコンパイルコード無しに起動時に即座にリクエストを提供する。しかし、動作中は、HHVMは最適化の機会を探すためにコードを分析する。最初の数回は一部コードが実行され、HHVMは全く最適化しない。最もありふれた方法で動作させる。しかし、そうしている最中、様々なコードが実行を要求される回数をカウントし続け、プログラム中の「ホットな」(良く呼び出され、実行に負荷のかかる)コードのプロファイルを少しずつ作っていく。

なので、最初はそのまま実行、その後はめっさ早くなるという特性があります。たしかに、HHVMを再起動し、最初のアクセスは遅いけどその次にはバカみたいな速さを叩き出してました。スクリプト言語のインタプリタが大体抱える問題を解決している感じですね。PHP7との速度比較記事もありましたが、PHPの実行環境がある程度のところで限界を迎えるのに対して、HHVMは余裕な数をだしてますね。これはいずれ僕も自分でベンチマークをとってみたいと思います。

ただ、今回の出題ではPHPの実行速度があまり問題じゃなかったのでISUCONでスコアは伸びませんでした。つらい。

nginxとh2oの比較

nginxの設定を散々見直したんですが、動的言語の実行が走る場合はフロントに立つWebサーバの設定についてはUnix Domain Socketを使うほうがはっきり言って速いです。当然なんですがLinuxの使えるポートには限界があって、その一つをローカル通信のために使うのはもったいないですし(たくさんあるからという意見は認めません)Unix Domain Socketが一本道でいけるとするなら、ローカルなのにポートで通信するのはたくさんの扉のある道を回り道するようなものです。(なんか微妙な例えですが)

worker_processesに関しては思いっきり上げました。コア数は4とかだったんで、業務だったらコア数と同じにしておくのですが、今回は競技だったってこともあって10とかに設定し、worker_connectionsを10240とかにしてました。

nginxは後ろのHHVMにつなぐリバースプロキシの仕事もしてもらうので、キャッシュもろもろの設定もしました。いらないページとか結構あるんですけど、その辺フロントである程度返してもらえると軽くていいですね。

まあ、フロントのWebサーバなんてやることこんなもんなんですが、時間がある程度経ってからのびすけ氏から

「しょーへーさん、h2o試してみません?」

っていう提案を受けました。h2oはKazuhoさんが開発している新しいWebサーバですが、なにやらめっちゃめっちゃ速いらしいです。なにやらデフォルトでnginxをばりばりチューニングしたものと同じくらいでるとか。

で、試したんですがこれubuntuでうまくコンパイルできずに止まってしまいました。これは悔しいのでまたリベンジですね。 HTTP/2に対応してあるのであれば業務でもぜひ使ってみたいです。まだあまり調べてない。

もちろんわかる方はわかると思うのですが、今回の出題にnginxの高速化とかキャッシュとかあまり効果なかったんでスコアは伸びませんでした。げぼあ。

MySQLのチューニング

いろいろしましたがなんか覚えてません。とりあえずメモリにバカスカ余裕があったのでmax_connectionsとメモリに持てるキャッシュの数値をガチ上げしたのは覚えてます。

Linuxカーネルに対してのリアルタイムパッチとコンテキストスイッチ

YAPCでkazeburoさんがコンテキストスイッチ周りの話をしていたので、ここの対策を練りました。きちんと処理を見積もってあげれば処理速度は20倍くらいいけそう、っていうのを調べてありました。カーネルのコンパイルを走らせて、カーネルのdpkgができた……まではよかったんですが、インストールするとシステムが読み取り専用になる悲劇。

ここから原因究明ができず、コンテキストスイッチ対策は諦めることになりました。

解説をしておくと、コンテキストスイッチはプロセスやスレッドから別のプログラムにCPU処理を切り替えることです。Linuxさんはこのへん高速に切り替えながら並列に見せかけた処理をしているんですけど、その待ち時間が結構きます。

そんなわけで、これを短縮させようぜっていうパッチがRT-Preemptパッチですね。こいつを当てて適切に設定すればいいはず。

なーんて、うまくいくはずもなかったんですね。ここはまた勉強してリトライです。ぐぬぬ。

でもこう言ったLinuxカーネルの深層に対して前もって勉強ができたのはとてもいい経験でした。

ファイルシステムのディスクバリア解除

どんどん下に降りて行きますよ! 今度はファイルシステムのディスクバリアを解除します。

ディスクバリアってのはext4から実装された機能なんですが、実際にディスクに書き込むときにいくつかの手順がきちんと終了しているか確認してからコミットを行ってくれる設定ですね。大事なデータをあつかうデータベースがあるサーバとかはあったほうがいいですが、何しろ競技なんでこれを外します。教えてくれたデプロイ王子こと廣瀬大明神に感謝です。

設定はfstabに書いて再起動すればいいんで一瞬でしたし、ディスクの書き込み速度も改善がみられました。

大事なデータを扱わないWebサーバとかならオッケーかもですね。

まあ当然だけどこんなとこ今回のところには関係なかったしスコアも上がらなかったですね!! 泣くわ!

カーネルパラメータのチューニング

とりあえずネットワークのパラメータでもガン上げしときますかね。

Linuxって最初IPV4 / V6の受信バッファの最大サイズがやたら小さいのでこの値を大きくしてやります。あとカーネルが処理できる数をネットワークパケットがくるときに備えて数を増やすとかごりごりやりました。この辺の細かい設定はあとでQiitaにでもあげます。シェアメモリとかもろもろ本当に細かくやりすぎてここでは書ききれませぬ。

この辺にくると自分のやっているのは正しいのかすごく辛くなってきたんですが、とにかくやるしかないって感じですね。サーバ側のベンチマークは早くなってるのに、スコアに現れないというのはサーバ・インフラを触っててとてもしんどいですね。

最後はsysctlに書いてサーバ再起動。反映されてればオッケー。今回こう言った地道な作業をすればサーバのスピードは確実に早くなるってことはわかったので、今後も活きて来そうです。

Systemdと仲良くなれた

いろんなところからいろんな声が聞こえるsystemdですが、仲良くなれました。まあ微妙っちゃ微妙ですし、disりたく気持ちもわからなくはないのですが、最新版のLinuxが取り入れているということはそれ相応の理由があるのでしょうし、使い方は覚えておいて損はないと思います。

といっても考え方はすごく単純で、chkconfigとinit.dのスクリプトを全て一つのコマンドでできるようにしているものです。

停止が「systemctl stop isuxi.php.service」起動が「systemctl start isuxi.php.service」でした。あとは起動時に有効にするかどうかはstop / startをdisable / enableにかえるだけ。ChefやPuppetのserviceと同じですね。

ただ今回時間もなかったし焦ったんですけど、systemdと速攻で仲良くなれたのはよかったです。これで安心してCentOS7に挑めます。ありがとうISUCON。

Ubuntuでも怖いと思わなかった

僕は社会人になってからずっとRedHat系でやってきたエンジニアで、DebianやUbuntuは以前から趣味意外では手をいれたことはありませんでした。でも今回触ってみて、ああ、なんとかなるなとは思いました。フォルダ構造や使われているミドルウェア、プログラムさえ理解すればあとは変わらないですし。

GCPはいいよ!

前職でGCP使ってたこともあってすっとはいれました。あれ、わからない人は本当わからないですが僕は結構やりやすいんですよね……まあ、人間好みもありますし、騒ぐことでもないのかなって。

まとめ

今回のポイントはDBのN+1周りだったらしいので、この辺解決できずにタイムアップしたのでスコア落として予選敗退でした。でもアプリレイヤーとDB構造の正規化まで切り込めたら二人に迷惑をかけずに済んだのかなと思うと悔しいです。個人的には初めてはいった職場がそうだったように、DBの正規化までがインフラエンジニアの仕事だと思うので、もっともっと余裕持ちたかったです。本当に二人にはもうしわけない気持ちでいっぱいです。

来年、またリベンジしたいな。

以上、負けてしまったエンジニアのISUCON反省会でした。でも最後チームのみんなで飲んだビールは超美味しかった。