ISUCON8予選1日目にチーム「SELinuxはEnforcing以外あり得ない」で参加しました

チーム「SELinuxはEnforcing以外あり得ない」でISUCON8に参加しました!

メンバーはいつもの @matsuu @ishikawa84g @netmarkjp の3人。

最終スコアは26,221。 もちろんSELinuxをEnforcingにした状態で計測しました。

最終結果はまだわかりませんが、たぶん無理でしょう。。。厳しい。

今年の言語選択

ここ数年は言語選択で迷走してて、毎年「去年の反省を踏まえ」て失敗しています。 「正規表現ネックみたいにGoがあからさまに苦手な処理じゃなければGoでやろう」と話してはいたものの、 基本的なスタンスとして反省を踏まえるよりも自分の軸が必要そう。

  • ISUCON5: Goで準備。開始時に「Go実装にはバグがあります」と言われて開始後に急遽Pythonに切り替え、FWがbottleだったりして爆死
  • ISUCON6: Goで準備。Goが苦手な問題。Goに見切りをつけるのが遅くなり爆死
  • ISUCON7: 昨年の反省を踏まえPythonで準備。今回はGoのほうが得意。Goなら1秒sleepのあたりで時間使わずに済んだけどPythonなのでいろいろ試行錯誤した
  • ISUCON8: 去年の反省を踏まえてGoで準備。今回はGo版だけ(我々にとって)致命的なバグがあったらしく、結果としてはGoじゃないほうが楽だった

今回はGo版のみのバグがあったんだけど、ISUCONはもともと

「ぼちぼちやってたWebサービスがあって、なんか偉い人が "18:00に広告枠買ってきたらよろしく頼むよ!" って言ってきた!」

というストーリーだったりするわけで、バグがあってもなくてもなんとかいい感じにするというのが使命なのですよね。 最近その気持ちを忘れていたので来年からはまた気持ちを入れ替えてやっていきたい。

やったこと

事前

午前

  • CentOS7のvimでvim-goが動かないのでneovimをインストール
  • sshrcでシェル、neovim設定を投入
  • go 1.11 をインストール
  • アプリ再起動したりログを消したり => prepare.sh
  • kataribe, pt-query-digestで分析して実行ごとにディレクトリに保存する準備 => analyze.sh
  • ひとまずgo版に入れ替える
  • 利用しているプロダクトを調べる
    • 事前に「h2oの可能性ある?、まさかねー、ないよねー」と思ったらh2o

  • アプリの仕様把握( 主に @ishikawa84g )
    • イベントを作成した際にベース価格が反映されないバグでしばらく迷子
  • 席数が固定だと確認できたのでシート関連をコードに埋め込み
  • ランダムに席を発行するのが時間かかるんだ!ということで1から順番に埋めてみた => ベンチでfail
  • 昼食はすき家

午後

  • ベンチfailに苦しんで抜けられず
    • //admin/ とデータがずれてる、 DELETE でエラーになる、などが発生
    • デッドロックなども発生しまくり
    • ベンチマーカーの報告にある403レスポンスの回数がh2oのアクセスログより多くて混乱したりしてた
  • いろいろ試してどれが残せてるかもうワカラン状態に...
    • ランダムに席を発行するところを高速化するために、シートごとにランダムな値をあらかじめ付与してその順番で発行するようにした(どのイベントもすべて同じ席から払い出される)
    • 残席数テーブルを用意して残席数はそこから取得するよう変更 => failしたので events テーブルにカラム追加に変更(戻した)
    • reservations テーブルに updated_at カラムを追加して IFNULL を削減
  • h2oで静的ファイルが304返せるよう変更
  • 3台に分散したところ、failがひどくなったので1台に戻す
  • 15:00過ぎにSELinuxをPermissiveに、17:30過ぎにSELinuxをEnforcingに

まとめ

  • アプリの理解力・理解スピード・正しいコードに対する意識が課題
  • 今回のGoのコードがすごく読みづらかったんだけど、初手で読みやすくするリファクタリングはしてもよかった
    • handlerの実装がほとんど main() に入ってて、いまどのエンドポイントの処理を見てるのかがわかりづらかったけど、そのくらいは安全にできるので関数に切り出したらよかった
  • そもそも高負荷を経験したことがないアプリなのであれば、実際きちんと動く前提をおかないほうがよい
    • そしたら、トランザクション内でトランザクション使わないDB接続したらおかしい、とか気づけるはず
Event 

See also