Upgrade to Pro — share decks privately, control downloads, hide ads and more …

秒間 10,000 リクエストを "簡単に"いなすゲームサーバーを Laravel で作る設計

秒間 10,000 リクエストを "簡単に"いなすゲームサーバーを Laravel で作る設計

1秒間に PHP が受信する HTTP リクエストが最大 10,000 回以上———
そんな世界が存在します。その一つが 「ソーシャルゲーム」 です。メンテナンスが明けた瞬間、イベントが始まった・終わる瞬間、様々なタイミングでゲームサーバーは瞬間的に高負荷になります。もちろん、サービスをリリースし PR をたくさん出し始めたその瞬間が、プロジェクトで最も高負荷となるでしょう。それらに耐えうるサーバー構成が求められていますが、「リリース直後にサーバーがダウンした」「限定イベントが始まったらすぐ緊急メンテナンスが始まった」という話はちょくちょく聞こえてきます。その 瞬間的な高負荷(いわゆる "スパイク") に耐えるには、事前準備を怠らないことが重要です。
ソーシャルゲームにおいては、他の Web アプリケーションに比べ 書き込みヘビーなワークロード であることが多いです。読み込みは比較的簡単に分散できますが、書き込みを分散することは容易ではありません。
そういった要件を達成するため、私のチームで行っている、 Laravel による高負荷に耐えるサーバー設計をご紹介したいと思います。

Masaru Yamagishi

June 26, 2023
Tweet

More Decks by Masaru Yamagishi

Other Decks in Programming

Transcript

  1. 概要 1秒間に PHP が受信する HTTP リクエストが最大 10,000 回以上——— そんな世界が存在します。その一つが 「ソーシャルゲーム」

    です。メンテナンスが明けた瞬間、イベントが始まった・終わ る瞬間、様々なタイミングでゲームサーバーは瞬間的に高負荷になります。もちろん、サービスをリリースし PR をたくさん 出し始めたその瞬間が、プロジェクトで最も高負荷となるでしょう。それらに耐えうるサーバー構成が求められています が、「リリース直後にサーバーがダウンした」「限定イベントが始まったらすぐ緊急メンテナンスが始まった」という話はちょ くちょく聞こえてきます。その 瞬間的な高負荷(いわゆる "スパイク") に耐えるには、事前準備を怠らないことが重要です。 ソーシャルゲームにおいては、他の Web アプリケーションに比べ 書き込みヘビーなワークロード であることが多いで す。読み込みは比較的簡単に分散できますが、書き込みを分散することは容易ではありません。 そういった要件を達成するため、私のチームで行っている、 Laravel による高負荷に耐えるサーバー設計をご紹介したい と思います。 - 高負荷案件でも Laravel は使えるの?と疑問に思う方 - どのようにスパイクをさばいているのかを知りたい方
  2. 秒間 1 リクエスト クライアント サーバ HTTP Req HTTP Res Done!

    — 約 1 秒後 — HTTP Req マタキタ ヨ HTTP Res ソウナノ
  3. 秒間 1 リクエスト クライアント サーバ HTTP Req HTTP Res Done!

    — 約 1 秒後 — HTTP Req マタクル ネ HTTP Res アイヨ Done!
  4. 秒間 1 リクエスト クライアント サーバ HTTP Req HTTP Res Done!

    — 約 1 秒後 — HTTP Req HTTP Res Done! 以下続く...
  5. クライアント サーバ 秒間 10 リクエスト HTTP Req x 10 コンニチ

    ハ コンニチ ハ コンニチ ハ コンニチ ハ コンニチ ハ コンニチ ハ コンニチ ハ コンニチ ハ コンニチ ハ コンニチ ハ
  6. サーバ 秒間 10 リクエスト HTTP Req x 10 HTTP Res

    x 10 ワア クライアント アリガト オオキニ タスカル ヤッタ セヤナ オケ ワーイ ドウモ アザス ウィッス
  7. クライアント サーバ 秒間 10 リクエスト HTTP Req x 10 クレ

    データ ホシイ ヨコセ マダー ハヨ ナニシテ ン ツギノ コレ ヨロシク HTTP Res x 10 マタキタ Done! HTTP Req x 10
  8. クライアント サーバ 秒間 10 リクエスト HTTP Req x 10 ヨイショ

    ヤッタ ドモ ザッス ワーイ マタクル ネ ヨロシク コレダ フム サラバ HTTP Res x 10 イソガシ Done! HTTP Req x 10 HTTP Res x 10
  9. クライアント サーバ 秒間 10 リクエスト HTTP Req x 10 ヨイショ

    ヤッタ ドモ ザッス ワーイ マタクル ネ ヨロシク コレダ フム サラバ HTTP Res x 10 ヒエー Done! HTTP Req x 10 HTTP Res x 10 以下続く... Done!
  10. 秒間 10,000 リクエスト(rps) の負荷って? - 約 10,000 台のクライアントが一斉にリクエストし始めること - その状態が「ずっと続く」こと

    - クライアント 1 台と比べて 10,000 倍の負荷がかかること ※以下リクエスト・パー・セカンド「rps」という
  11. 書き込み DB の CPU がカツカツ 今回は Amazon Aurora を使ったが、これは CPU

    80 % 以上いくと急に不安定になる 傾向がある 70 % ならまだ安定稼働するが、これ以上の負荷は厳しい まだまだスケールアップは可能だが、アップには限度があるし何より費用がかさむ
  12. コネクション数には限界がある MySQL の仕様上 max_connections は 1 台あたり 16,000 が限界 今回

    10,000 rps で 9,000 ということは、 20,000 rps は耐えられないということ RDS Proxy で改善されるかもしれない? NewSQL も選択肢?
  13. アプリ設計の要 - クエリ最適化が容易であること - 発行されるクエリが明快であること - ドメイン実装とクエリ最適化を分離して作業できること - ドメインが大規模になってもスケールすること -

    疎結合であること - どこで何が実装されているかわかること - 運用を考えて、依存関係のアップデートが容易であること - Framework 等のバージョンアップがしやすいこと
  14. DDD-like Driven Design の三つの原則 1. Laravel Frameworkは利用するが、 Framework とドメイン実装は分離すること 2.

    責務がネームスペースごとに分離されていること 3. ネームスペースごとの依存関係が明らかで、 片方向になっていること
  15. ドメイン アプリケーションの本質的な実装部分 use Illuminate\...; と書いたら処される ※ Illuminate\Support ネームスペースは除く Domain から

    Domain 外部方向への依存は基本的に NG 必要であればインターフェースを定義して別の場所で実装
  16. その他インターフェース Domain の実装の中で S3 にアクセスしたい、 Laravel のこの機能を使いたい、などと いった場合は、 Domain で

    Laravel や S3 を参照するのではなく、単純に欲しいイン ターフェースを定義するだけとする 具体的に接続したりリクエストを送ったりするのは Domain の本質ではないので「イン フラストラクチャ」に分離する ※クリーンアーキテクチャっぽい考え方でもある
  17. Why?: Active Record 型であること Eloquent は Active Record 型 ORM

    大規模アプリケーションにおいて Active Record を適切に運用するのは難しい(もちろ ん不可能ではない) 今回の DDD-like DD において大きな課題となった 対照となる Data Mapper 型 ORM の必要性が高まった
  18. まとめ - 秒間 10,000 リクエストをさばくのは Laravel でも安定していける - RDB 負荷をいかに捌くかがキモ

    - DDD-like DD は結構良いぞ - 例えば Eloquent を投げ捨ててみると道が開けるかも インフィニットループでは、札幌・仙台で働くエンジニアを募集中! ご清聴ありがとうございました!