最大アクセスの5倍に耐える!Confit性能改善レポート
目次
こんにちは、Confitプロマネの荒木です。
Confitは年々導入が増え、「他の大会でもConfitを使いました!」「アプリもダウンロードしましたよ!」といった嬉しいお声をいただく機会も増えてきました。
今回は、大会当日に皆さんが利用するConfitオンライン公開サイトの性能改善の取り組みを紹介します。
見た目や機能だけでなく、裏側のパフォーマンスや安定性の向上に日々取り組んでいることが少しでも伝わればと思います。
なお、今回の改善はエンジニアの提案からスタートした自主的な取り組みであり、プロダクトをより良くする姿勢や、それを周囲が歓迎する文化が根付いていることを改めて感じる機会でもありました。
そんなアトラスの開発現場の雰囲気も、このブログを通じて感じていただきたいです。
取り組みの背景
2025年3月でモバイルアプリの開発がひと段落したことを受け、 「ここで一度、機能以外の方向性でも、ユーザーに価値を届けられる取り組みを考えたい」と考え、開発チームでアイディアを出し合いました。
その中で、特に以下の2点が現状の課題として浮かび上がりました。
- UI/UXや機能面では多くの改善が実現されたものの、「表示速度が劇的に速くなった」という体感が得られておらず、パフォーマンス面で継続的な改善の余地がある。
- アクセス増加が見込まれる場合、都度サーバー増強で対応してきたが、「そもそも増強が必要なのか?」「何台増やせば十分なのか?」といった明確な判断基準が少なく、可用性を優先して“多めに増やす”判断になっている。スケーリング判断を数値的な根拠をもとに行えるようにしたい。
2に取り組めば1についても一定の効果が期待できるだろう、という見立てのもと、今回は2を主な改善ゴールと定めました。
Confitオンライン公開サイトに要求される処理能力とは?
さて、性能改善に取り組むにあたり、「そもそもどれくらいのアクセスを捌ければいいの?」という目標設定が必要です。
そこで、Google Analyticsのデータをもとに、過去2年間でもっともアクセスが集中したタイミングを指標として採用し、そのときのトラフィックに耐えられる処理能力を目標に設定しました。
※厳密にはアクセスログから1秒あたりの最大アクセス数を算出するのが理想ですが、今回はやや簡易的な方法で算出しています。
過去もっともアクセスが集中した日は?
過去2年間で最もアクセスが多かった日は 2024年9月5日でした。ちなみに、学術大会は3月と9月に開催が集中するため、そのどちらかの月にピークを迎えることが多いです。
最大アクセス時のアクティブユーザー数と表示回数(2024/09/05)
1日あたり約45万PVというのを見て、「こんなにアクセスされてるんだ…」と改めて実感しました。
過去最大アクセスに耐えうる処理能力は?
2024年9月5日のうち最もアクセスが集中したのは午前10時台でした。この時のリクエスト数を元に、目標となるスループット(1秒あたりのリクエスト数)を定めました。
- ピーク時のリクエスト数: 約11万リクエスト/時
- 秒間リクエスト数に換算すると:
110,000 ÷ 60 ÷ 60 = 約 31リクエスト/秒
2024/09/05 時間帯別アクセス数(Google Analytics)
やったこと
ここからは技術的な話が続くので、「結果だけ知りたい!」という方は「改善結果まとめ」にお進みください。
Node.jsプロセスの並列化(クラスタ構成の導入)
今回の改善における最大のポイントは、Node.jsのプロセス並列化です。
Node.jsはデフォルトでは1台のサーバーで1つの処理を担当する、シングルプロセスで動作するため、処理性能に限界があります。そこで、複数のプロセスを同時に実行できる構成に変更し、処理能力を向上させました。
ただし、並列化によってCPU使用率が上がったことで、低負荷時は性能向上が見られた一方、高負荷時には逆に処理が不安定になるケースが発生しました。
これを解消するためにフロントエンド処理を担うWebサーバーのCPUリソースを増強したところ、高負荷時でも安定して高い性能が発揮できるようになりました。
初期表示パフォーマンス改善のためのJavaScript 最適化
次に、Google PageSpeed Insightsを使って、実際の公開サイト(2024年第85回応用物理学会秋季学術講演会)のパフォーマンスを分析しました。
測定の結果、「使用していないJavaScriptが初期表示時にも読み込まれている」ことが、表示速度の低下につながる要因であることがわかりました。
Confitのオンライン公開サイトはSPA(Single Page Application)の体験を実現する構成となっており、JavaScriptで画面描画を行うため、初期表示時のJavaScriptの最適化が特に重要です。
そこで、以下のような改善を実施しました。
- JavaScriptファイルの転送量削減
- 不要な処理の削除によるバンドルサイズの軽量化
- 静的ファイルの事前圧縮(br/zstd形式)対応
- 初期表示に不要な処理の排除
- ReduxのinitialStateから、非更新項目をprops経由で渡さないよう修正
- X(旧Twitter)埋め込みスクリプトの読み込みを遅延実行
- Googleタグマネージャのスクリプト呼び出しを1回に制限し、不要な初期通信・処理を削減
API・ログ処理の軽量化
初期表示に関係するバックエンド処理についても、以下の改善を行いました。
- APIレスポンス評価を遅延実行
- ログ出力処理を軽量なpinoライブラリに変更
- 同じAPIリクエストが短時間に複数回発生した場合、2回目以降はキャンセルし、処理中のレスポンスを使い回す、in-flight request deduplicationに対応
- Reactコンポーネントをキャッシュ(メモ化)し、状態が変わらないコンポーネントの再描画をスキップ
CPU負荷の軽減
Node.jsの並列化によってCPUリソースの消費が増えたことを受け、サーバー側での負荷軽減にも取り組みました。
具体的には、Filter系のソート処理をサーバー起動時に一括実行し、これまでページごとのリクエスト時に毎回実行していたソート処理を、起動時に一度だけ行うよう変更しました。これにより、不要なCPU使用の継続的な発生を防ぎました。
負荷試験による効果検証
以上のような施策の成果を定量的に評価するため、Apache JMeterを用いた負荷試験を実施しました。
今回は未ログイン状態で負荷試験を実施したのですが、実際の運用では認証処理や表示切り替え等が加わるため、やや高めの負荷条件を意図的に設定しました。
負荷試験の結果、改善前と比べて約2倍以上の処理性能の向上が確認できました。
改善前 | 改善後 | |
---|---|---|
スループット | 約60リクエスト/秒 | 約150リクエスト/秒 |
レスポンスタイム中央値 | 約2〜5秒 | 約1秒 |
改善結果まとめ
処理性能の向上
- スループット:約60リクエスト/秒 → 約150リクエスト/秒と処理効率が2倍以上に向上しました。
- 「Confitのオンライン公開サイトに要求される処理能力とは?」で示した過去最大のリクエスト数(約31リクエスト/秒)の5倍の負荷があっても耐えうることを確認できました。
今後、大会の同時開催数が増えたとしても、追加のサーバー増強は不要と判断できる水準を実現できました。また、定量的な根拠に基づいたスケーリング判断が可能となり、運用の見通しと安心感が大きく向上しました。
ただし、今回の負荷試験は未ログイン状態かつ特定の操作パターンに基づいたものであり、すべてのユースケースを網羅しているわけではありません。
また、レスポンスタイムの外れ値として、一部リクエストで最大5秒程度かかるケースも観測されています。今後は、レスポンス分布の分析やログの精査を通じて、特定条件下での遅延要因を明らかにしていくことが改善課題となります。
サーバー構成の見直しによるコスト削減
今回の性能改善では、一部の構成でサーバースペックを上げましたが、全体としては必要なリソースを抑えた構成に最適化できたため、サーバーコストを約13.5%削減することができました。
性能向上と運用コスト削減の両立という、嬉しい副次的効果も得られた結果となりました。
おわりに
今回の取り組みにより、Confitオンライン公開サイトの処理性能を大きく向上させることができました。
同時に、開発チームの自発的な提案から改善が実現したことも、プロダクトとチームの成熟を感じる大きな一歩だったと思います。
とはいえ、サイトの表示速度に関しては、まだ改善の余地があり、今後は以下のようなキャッシュの活用がキーになると考えています。
- HTMLのサーバーキャッシュ
- ブラウザキャッシュ
- ファイル配信のエッジキャッシュ(CDN)など
これからも、ユーザー体験の質を高めるために、見えない部分の改善に取り組んでいきます。
