この記事は、ニフティグループ Advent Calendar 2023 19日目の記事です。
はじめに
こんにちは。会員システムグループの川上です。普段はiOS/Androidアプリ「マイ ニフティ」の開発をしています。(弊チームではエンジニアを募集中です!)
今回は、ISUCONという競技イベントにニフティ社員でチームを組んで参戦するにあたって実施した準備について紹介します。
イベント当日のレポートについては下記の記事をご覧ください。
ISUCONとは?
ISUCONは制限時間8時間でWEBアプリケーションを高速化してスコア化された性能を競い合うコンテストです。今年は11月25日に ISUCON13 が開催されました。
※ 「ISUCON」は、LINEヤフー株式会社の商標または登録商標です。
メンバー集め
私は去年の ISUCON12 が初参戦で、今年も出ようかな〜とゆるく考えていました。
そんなとき、ニフティの部活制度でISUCON部を作らないかという話が出て、その流れで部員の中から自分を含め3名の出場メンバーを集めることができました。
ちなみにニフティの部活には、フットサル部やe-sports部など幅広いジャンルがあります。
参戦するまでにやったこと
1. 初心者向けの問題を解いてみる
基礎的なノウハウから学ぶため、ISUCON本と呼ばれる下記の書籍を各メンバーが購入しました。
達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践
ザックリと全体を読んだ後、まずはシンプルな問題でISUCONの典型的な流れを体験することにしました。そのため、ISUCON本にも登場するpixiv株式会社の社内ISUCON「private-isu」を解くことから始めました。
https://github.com/catatsuy/private-isu
進め方は初出場のメンバーがドライバー、それ以外のメンバーがナビゲーターをして、実際のISUCONの流れに沿う形で学習しました。
例えば、下記のような内容です。
- マニュアル確認
- systemctl・journalctlをはじめとした基本的なコマンド
- alp・pt-query-digest等の計測ツールの使い方
- mysqlやnginxの設定
- インデックス追加、N+1の解消
また、理解をアウトプットする場として、社内でハンズオンを開催しました。そのときの様子はぜひ下記の記事をご覧ください。
2. 過去問を解いてみる
ISUCONにおいて最も効果のある練習法は過去問を利用した素振りだと思います。
私のチームでも、もちろん素振りをしました。今回は技術的に新しいコンテストの方がマッチしているため、ISUCON 11予選と12予選を実施しました。
環境の構築はAWS上に行い、下記のリポジトリのAMIを利用させていただきました。
https://github.com/matsuu/aws-isucon/tree/main
この時点では、時間制限を設けることがなく、気が済むまで思いついた改善を試していきました。練習した項目は主に次の項目です。
- nginxによる静的画像の配信(認証なし/あり)
- キャッシュ戦略(Redisなど)
- 外部コマンド呼び出し解消
- インデックス追加、N+1の解消、テーブルの変更
解いた後は公式の解説を読み、実施できていなかった改善を挑戦しました。
本当はその後、本戦の問題や8時間制限での素振りをした方が良かったのですが、時間の都合により叶わずでした。
3. 本番の直前準備
本番1週間前には下記のようなことを改めて振り返りました。
- デプロイ等のスクリプト準備
- 初動の役割分担
- 再起動試験のタイミング
デプロイ等のスクリプト準備
本番中は「ベンチ → 計測 → 修正 → デプロイ」のサイクルを大量に回すため、それぞれを実行する時間を短縮することは重要です。対象のサーバーは複数台あるので、手動で行うより一括で実行できる方法を準備しておく必要があります。
今回は実行内容を4つに分割して用意しました。(ベンチはISUCON公式コンソールから実行されます)
- プロビジョニング
- デプロイ(ファイル同期とサービスのrestart)
- ログのtruncate
- 計測(alpやpt-query-digest等の実施)
私のチームではAnsibleの知識が疎かったため利用せず、練習段階ではGithub Actionsで実行していました。しかし、Actionsは立ち上がるまでの時間が長く、待ち時間が非効率に感じたため、シェルスクリプトに落ち着きました。計測だけはそのままGithub Actionsで行い、自動でIssueに結果を作成するようにしました。
また、シェルスクリプトを含めたリポジトリはテンプレートリポジトリとして、簡単に複製できるようにしておきました。
初動の役割分担
初期段階では未知のアプリケーションがサーバーに動作している状態から始まるため、可能な限り早く必要な情報を取得して、改善に入れるように役割分担が必要です。
私のチームでは次の3つで役割を分担して、やることをNotionのチェックボックスで管理するように認識を事前に合わせておきました。
- サーバーから必要なファイルの取り込み・デプロイスクリプトの整備
- ソースコード解読、SQLの抽出
- 当日マニュアル読み、アプリを触ってみる
完了時間の目標も定めて、1時間以内にデプロイスクリプトが動作し、並行してアプリの気になる点やマニュアルの概要をNotionに抽出することにしていました。(実際にはメンバーが最速で終わらせてくれて、10分ほどでデプロイできるようになりました)
再起動試験のタイミング
ISUCONには競技終了後にいくつか追試項目が存在します。そのなかに主催者が全サーバーの再起動後にベンチマークを実施して、再現スコアが最終スコアの75%以下の場合は失格になるという内容があります。
全チームに対して行う追試項目
- 再起動後の負荷走行でfailした場合
- 再現スコアが最終スコアの75%以下の場合
- envcheckを利用したサーバ環境の確認
最終スコアで上位のチームに対して行う追試項目
https://github.com/isucon/isucon13/blob/main/docs/cautionary_note.md#追試
- 負荷走行実行時にアプリケーションに書き込まれたデータが、サーバー再起動後に取得できない場合
実は私が去年参加したチームではこの再起動試験でfailになってしまい、ランキング外になってしまったという経験があったので、今回は17:00には一度再起動を試すように決めました。本番当日は焦りもあるので、忘れないように連絡に利用していたDiscordにもリマインダーを仕込みました。
おかげで、当日はリマインダーが来た時刻に再起動試験を行い、無事failになることなく追試OKでした。
おわりに
この記事では、私のチームがISUCON13本番までに実施した内容を振り返りました。事前の準備を固めておくことで、去年参加した際より、本番でスムーズに改善に取り組むことができ、見落としも少なくすることができました。
ちなみに当日の結果は661チーム中81位でした。
25,674 nisucon-bu
ISUCON13 受賞チームおよび全チームスコア
ISUCONは参加するたびWEBアプリケーション開発に足りないスキルを知ることができる貴重な機会だと思っています。最近は過去問も実施しやすい環境が整っているため、ぜひ未経験の方も体験してみてください!