Unyablog.

のにれんのブログ

ISUCON 10 本戦に出場した(16位)

チーム 😇😇😇 として ISUCON 10 本戦に参加した。

isucon.net

結果は 14206 点で 16位。くやしい!

レポジトリは以下。よく分からない Author になってるコミットは大体自分によるもの。

github.com

以下はチームメイトのブログ。コードの改善などは基本的にそちらを見てください。

blog.utgw.net

やったことなど

自分はいつもどおりサーバーを触る人だった。恒例になってきた一連の動作とパフォーマンスを除いて、今回特別にやったことや所感を書いていこうと思う。

Envoy

Envoy が入っていて「自分は Envoy の YAML を手で書いたことがあるぞ!!任せろ!!!」って張り切ったんだけど、実際には Envoy らしいことは特にしておらず普通の Reverse Proxy だった。さっさと Nginx に載せ替えても良かったと思う。 Envoy の設定って手で書くものじゃないしね…。

実際静的ファイルの配信をするために Nginx を導入したけど、当日は全てを Nginx に載せ替えることはしなかった。Envoy の設定には困っていなかったし、 ISUCON で使うと面白そうだったので😈。

気になった点としては、

  • 最後のほうで LimitNOFILE に到達して突然死した

    その時は時間がなくて雑に Restart することで解決したけど、後で調査した結果 LimitNOFILE 到達が原因だった。そういえば上げ忘れてたね…。それでも突然死はやめてほしいが、そういう思想らしい。

  • ベンチマーク中 CPU 使用率が 40% と高かった

    今まで ISUCON で Nginx を使ってたときは困ったことがなかったので意外だった。TLS 終端してるとそんなもんだったっけ?

手で設定しにくいということを除いても、普通の Reverse Proxy として使うなら Nginx のほうが扱いやすいなあと思った。

サーバー構成

今回はサーバースペックが3台とも違っていて、

  1. CPU 2コア メモリ 1GB
  2. CPU 2コア メモリ 2GB
  3. CPU 4コア メモリ 1GB

という構成だった。コンテスト中、構成は以下の変遷をたどった。

  1. サーバー1 単体

    初期状態。

  2. サーバー2: MySQL サーバー3: Web, API, Envoy, Nginx

    MySQL といえば InnoDB バッファプール!ということでメモリの大きい方に載せた。サーバー1は開発用。

  3. サーバー2: Web, API, Envoy, Nginx サーバー3: MySQL

    サーバー2を見ていたらメモリは 30% ぐらいしか使っていないのに CPU がサチってたので載せ替え。サーバー3はメモリも CPU も80%程度で良い感じ。

  4. サーバー1: API, Envoy, Nginx サーバー2: Web サーバー3: MySQL

    サーバー2 を見ていたら意外にも Envoy が食っていたので Nginx と API ごと 1 に載せ替えた。

この状態でリソース不足が起きることはなくなった。謎エラーがなければもっと伸びたよなぁ~~~~。

Protocol Buffers

今回 Web アプリの API には Protocol Buffers が使われていたので、デバッグのために Protocol Buffers を解読し打てるようにする必要があった。

色々考えた結果 Wireshark でパケットキャプチャして直接眺めることに。

ただ、色々難しいことがあり…

  • WiresharkTLS の解読ができない

    そういえば TLS の中身見れる機能があったな、って秘密鍵だけ持ってきたけど解読できなかった。まあ言われてみれば DH だしね…*1。新たな知見を得た。

    これは Envoy とアプリ間の通信を見ることで解決。

  • Wireshark で Protocol Buffers のパースができなかった

    最新の Wireshark だと見れる機能があるはずなのだけど、うまく行かなかった。Proto を Import するパスが間違っていた?それとも HTTP/2 や gRPC じゃないから見れない?*2

結局パケットキャプチャした内容をそのまま bytes で保存して、 protoc に噛ますことで見れるようになった。

$ cat /tmp/foo.bin | protoc --decode=xsuportal.proto.services.admin.InitializeRequest /Users/nonylene/codes/innocent-team/isucon10f/proto/xsuportal/services/admin/initialize.proto --proto_path /Users/nonylene/codes/innocent-team/isucon10f/proto

めっちゃむずかった!普通に Printf デバッグなりすればよかったね。

デバッグ用のリクエストを作るのも色々手間取ってしまった。初めはこれ gRPC だ!って勘違いしていたのでずっと grpcurl でやろうとして使い方がわからん…と言っていた*3。結局 curlprotoc を組み合わせて解決。

github.com

MySQL 8

予選は MySQL 5.7 だったけど本戦は MySQL 8 だった。

ISUCON 8 本戦で MySQL 8 にめちゃくちゃハマった経験があったけど、そのおかげもあって今回は全く困らなかった。 GRANT 文とユーザー作成を分けなきゃいけなくなったんだな~、ぐらい。

全体の感想とか

結局色々やったものの utgw のブログに上げられているエラーが解決できず、サーバーも本領発揮せずに終わってしまった。みんなで色々見てたけど分からず厳しかった!!

感謝

今年のコンテストも楽しかったです!今年は本戦もリモートとなりましたが、Tシャツや名札が事前に送付されたり、当日に YouTube ライブをしていたりとリモートでも盛り上がるように色々施策があって良かったと思います。問題解説ビデオ最高でした。

www.youtube.com

問題も解きごたえがありました。サーバーによってスペックが違うのも新鮮で、「とりあえず3つに分けとこ」だけではなくちゃんとサーバーのリソースを検討することを求められていて楽しかったです。

今年もチームメイトに助けられました。自分だけだと絶対出れてない(学生一人チームすごいよね…)し、バランスの良いチームだなあと思います。来年もやっていきたい!

*1:じゃあ RSA にするか、パフォーマンスも良くなるだろうし、と思ったけど Envoy での設定方法がわからなかっ上、ベンチマーカーが対応してるのかも不明だったのでやめた

*2:Protocol Buffers のライブラリを使っているだけなので、 Envoy とアプリ間の通信は HTTP/2 や gRPC ではなく HTTP 1.1 だった。

*3:途中で息抜きに外に出て考えたら「あっこれ gRPC じゃないじゃん」って気づいた。休憩は大事。