きょこみのーと

元六本木でGo書いてました。今はVRでGo書いてます。

ISUCON9予選にk02で参加して完全敗北しました #isucon

いつものメンバーでISUCONに参加して完全敗北...! いつもどおりGo書く人を担当。 最大スコアは3,120で、最終結果は fail 。

以下メンバーの感想。

alligatorswamp.hatenablog.com

事前にやったこと

  • scrapboxに色々使いそうな記事をまとめたり
  • ISUCON8予選の過去問の環境を構築して模擬したり
  • 使うツールの選定など

ISUCON9予選当日の作業の流れ(kyokomi目線)

  • 10:00 開始
    • ドキュメントを読む -> 読んでる途中にAlibabaでの環境構築を先にやったほうが良いと判断
  • 10:15 〜 10:15
    • Alibabaの環境構築完了
    • sshできることと、アプリケーションにログインできることを確認した https://gyazo.com/b8705539ea9092849d86721548d54399
    • 速攻でベンチマークを実行する image
    • ベンチ実行によってクレジットカードの認証が通らなくなったことに気が付かずメンバーの二人がわちゃわちゃしてた
      • しばらくjsのコードとか見た後にレギュレーションに書いてあったこと気がつく...
  • 10:00 〜 10:30
    • githubにpushする
    • scrapboxにメモってた手順のpush先が事前に素振りしたときのrepositoryになってて無駄に混乱した
    • image
    • github tokenでシュッとpushできるようにする手順書いてたのは正解だった
  • 10:30 〜 10:50
    • ファイル構成把握しながら、不要なファイル削除したり、gitignoreの設定を追加
    • ローカルで起動するようにflag追加、docker-composeの追加など
    • 初期データがローカルでなくて動かないことに気が付き120MBもあることからgitignoreされてるというやさしさに気がつく
  • 10:50 〜 11:30
    • テーブル構成を把握したかったのでER図作ろうとして外部キー貼ったら、初期処理でエラーになって「う〜ん?」って調べてたが本質ではないな...と30分くらい無駄にしてホワイトボードに手書きした
  • 11:30 〜 12:10
    • main.goのコードが長く、目的のコードがさっと見つけられず大まかな機能単位でfileを分けるリファクタに手をだした
    • 見通しはよくなったし改修時の対象を探すのも楽になった感じはある
  • 12:10 〜 12:30
    • Prometheusで監視できるようにmetricsのhandlerを仕込んだり
    • image
    • 結局ほとんど使わなかった...
  • 12:30 〜 13:30
    • マイページのtransactionsの取得がボトルネックぽいということで見始める
    • `status IN (?,?,?,?,?) AND ` がサクッと見て無駄そうなので消した(全ステータス指定してたので)
    • indexを貼った。queryの負荷はそこそこ減ったぽい(スロークエリ曰く) image
  • 13:30 〜 14:00
    • categoriesが32万回くらいselectされてたのでサクッとcacheした
    • 100〜1000回くらい?まではselect回数が減った(レコード数は40くらいなんだけど)
      • これはinitで全レコードcacheしたほうがよかったなとあとから思った
      • 一旦、できるだけ既存の実装から離れないように〜というポリシーでこうしてた
  • 14:00 〜 14:40
    • usersもcacheした
    • この時点の3120点になってた(そしてこれが最終的に最大スコア...)
  • 14:40 〜 15:00
    • なんかスコア上がらねーなと思い、このままgetTransactionを見ていっていいのか???と不安になり
    • キャンペーンを有効にしてみる?という話になって1に設定した
    • 結果なんかめっちゃエラーになる
    • そしてAPIGatewayErrorとtoo many connectionsがでまくる
    • DBのCPU使用率も落ち着く(これはミスリード...)
    • これを解消するのが鍵では!!!!!と作戦を変更(これが失敗だった...)
    • MaxConectionはアプリ側は一旦120に設定し、DB側(3号機)で300くらいに設定して一旦でなくなった
    • APIGatewayの502エラーが自分たちのNginx?と勘違いしてulimitか!!とか結構時間無駄にした
      • よく考えたらアプリログでNginxのログでるのおかしくね???ってなり、そこでようやく外部サービスやん...って気がつく
  • 15:00 〜 17:00
    • とりあえずログやmeasureでどれくらい外部APIが叩かれてるのかを可視化したり
    • statusの取得が無駄っぽいから wait_done 以外は shippings のテーブルの結果を見てresponseに設定したりを入れてリクエストを減らしたり
    • item購入時にreserveするの不要そう?(実際にshipするときでいいのでは)と判断し、shippingsテーブルのreserve_idとかをNULL許可にしてうまいことshipするやつだけreserveの外部APIを叩くようにしてリクエストを減らしたり image
  • 17:00 〜 18:00 終了
    • ずっとキャンペーン有効による外部APIのGatewayTimeoutをなんとかせねば〜と試行錯誤していてFailしたままなのでなんとかしなければと焦り始める
    • 502エラー速攻で返すくらいならタイムアウトギリギリまでRetryしたほうがいいのでは?と、適当に1秒sleepして3回までRetryするbackoff的な実装を強引にGOTO文で実装したりしたがしかし...
    • 結局最後は10回Retryしてタイムアウトになり、じゃあ5回だ!!とか完全にヤケクソ状態の山賊状態だった...
    • 10ってコメントのpushなのにコードは10 -> 5に変更っていう...もうむちゃくちゃ...
    • もう何と戦ってるか本人達もわかっていないまま試合終了してしまった... 〜完〜

まとめ

  • 想像を上回る良い出題ですごく楽しかったです
  • レギュレーション大事だよな...!って毎回わかってるつもりだけど終わるまで色々気づけてなくて悔しい
  • なんかいっぱいAPI叩かれてるね。なんかめっちゃCPU上がってるね。の深堀りができる状況になってなかった
  • 悔しい...!来年こそは...!