ISUCON6

毎年恒例のISUCONに参加(オシャレ怪盗スワロウテイル)してきました。今年で4回目の挑戦になります。

ISUCON6予選

いわゆる、はてなキーワードクローン実装です。

加えて、各機能が別アプリ(別プロセス)で動作しており相互間はAPIでやり取りするという構成でした。 厳密な実装をするならキャッシュ戦略があまり効かないアプリケーションです。ただ、今回ベンチマーカーでPOST後適切にリンクを生成していなくても一発failとならず減点だけとなるのでキャッシュで押し切ってもなんとかなったという感じでした。

時間内にやったことは、

  • まずは、マイクロサービス化されている実装(isutar、isuda)を統合する
  • データ永続化部分をMySQLからRedisに置き換え
  • さらに初期データをすべてhtmlfyしたものをRedisに乗せておく

といったところまで実装し、POSTが来たらキーワード毎のflagを見てキャッシュをパージ、というところまで実装したかったのですが時間が及ばず終了。 なんとか予選を突破できました。

ざわざわしていたGoですが、予選後、試してみてたしかにGoのregexpは遅く、正規表現ではなく単なる置換ですむので strings.Replacer 大躍進というのは良い知見でした。

ISUCON6本選

pixivさん作の問題だけあってpixiv sketchのミニマム実装で、使われている技術要素としてSSE、React、サーバサイドレンダリング、そしてDockerというモダンな構成でした。

最初難儀したのは、各ミドルウェア、アプリケーションがDocker Composeで動作しているので各アプリのログ出力がまったくない!という状態で、スタートしたので、ベンチマーカーの挙動を素早く追えなかったことでした。

Dockerだと、短時間に何回も再起動を繰り返すことになりかえって足かせになるので、

  • MySQLをDockerからhost側に移行
  • nginxをnodeの前に建てる(http2化)

ということを進めました。

ここで、すでに15:00くらいと大きく時間を使ってしまい、慌てることに。 加えてnginx化した段階で初期スコアより大きく下がりさらにさらにあわてることに。 nginx化したことにより、クライアントからのリクエスト要求を受け付けられるようになり、その結果、/img/:id で詰まり(大量のTIME_WAIT)、ベンチマーカーがワークロードを下げたことが原因でした。

ここをまず突破しないと先に進めないぞということで、

  • nginxのproxy_cache
  • nodeにおける /img:id をやめる

ということを戦略としました。 proxy_cacheは 画像の変更 = 画数の変更 ということから、リクエストパラメータにstroke_countを持たせる(/img/:id?s={stroke_count})戦略が良さそうとなりました。 そして、nodeでどうやらつまるのでRuby(thin)でリクエストを捌かせようようという試みでした。

この2つの戦略を進めようとしていましたが、完成させることができずタイムアップとなりました。 懇親会で他チームの話をきいているともうちょっとうまくやれた感じがして悔やまれる…

ちなみに、上記とは別にいろいろやっていたのですが、どれもまずはトップページのからの /img/:id を解決しないことには意味のないものばかりでした。

  • N+1を解決する
  • 特定のキャッシュのパージを実現するためにproxy_cacheではなく、nginxからmemcachedを参照する方法。結果としておそすぎてだめ(1リクエストに100msくらいかかっている)

予選と本選通じて

毎年ハードルが上がっているのを感じていますが、ISUCON6でまた一段難しさが増したという感じでした。 運営、問題作成者みなさん、ありがとうございました。

やはり3人というチーム構成はいいバランスになって良いなと思います(フォローしあいつつも効率的に動ける)。チームメンバに感謝を。

また来年もリベンジです。