マイクロサービスとゲーム

こちらは [AWS for Games Advent Calendar 2022](https://qiita.com/advent-calendar/2022/aws-for-games) 最初の1日の記事になります。

昨今新しく開発されるゲームタイトルは巨大化、そして複雑化しています。その巨大で複雑なゲームの裏側にあるバックエンドそしてインフラストラクチャ、様々な構成の仕方がありますがその中でもよく議題に挙がるのがマイクロサービスアーキテクチャです。今回の記事ではそんなマイクロサービスとゲームの相性、そしてハードルが高く見られがちなマイクロサービスの始め方を話したいと思います。

宣伝は早めにしておいた方がいいので、この記事を読んで実践的なマイクロサービスのサンプルを見てみたくなった方は AWS のデベロッパー向けウェブマガジン [builders.flash](https://aws.amazon.com/jp/builders-flash/?awsf.filter-name=*all) に投稿されている２つのゲーム記事 [Amazon DynamoDB で作るサーバーレスなゲーム用アチーブメントマイクロサービス](https://aws.amazon.com/jp/builders-flash/202205/serverless-game-achv-microservice-dynamodb/?awsf.filter-name=*all) と [Amazon DynamoDB で作るサーバーレスなゲーム用フレンドマイクロサービス](https://aws.amazon.com/jp/builders-flash/202209/dynamodb-serverless-friend-microservice/?awsf.filter-name=*all) をチェックしてみて下さい！
# マイクロサービスやってますか？
いきなりですが皆さんマイクロサービスやってますか？マイクロサービスについては様々な見解があると思います。ここではすでにマイクロサービスやられてる方も、やってない方も、難しいと考えている方も、苦手だと思っている方も気軽に読めるようにメリットとマイクロサービスの始め方を中心に話していきます。モノリスが悪いや、全てマイクロサービスにするべきといった話では無く、今後巨大で複雑なゲームのバックエンドにマイクロサービスを考慮する際に役に立つ、ゲームとの相性にフォーカスした１つの考え方のお話です。
# モノリスの壁とマイクロサービスにしたくなる要素
モノリシックなアプリケーション、モノリシックなゲームバックエンドを開発しているといくつかの壁に当たる事があります。特に大きな物としてあげられるのがスケールの壁、コケた時の壁、デプロイの壁、そして開発選択肢の壁です。具体的にゲーム開発の中でどういったシナリオがあるか見ていきましょう。
- スケールの壁
    - モノリシックなバックエンドはスケールする際サービス全体がスケールします。例えばゲームの一部機能であるマッチング機能にのみ負荷がかかっている状態だとしても、バックエンド全体をスケールさせる必要があり必要以上のリソースを消費する必要があります。
- コケた時の壁
    - モノリシックなバックエンド内で予測していない事態が起きた時サービス全体を停止させる必要が出てきます。例えばチャット機能の中でエラーが発生した場合、例えチャット無しでもゲームが遊べたとしても、エラーの影響範囲が定かで無い限り一度サービスを止めメンテナンス等で修正するといった事があるでしょう。
- デプロイの壁
    - これはコケた時の壁と似ています。機能追加や機能修正にパッチが当てられるというのはよくある事です、しかしモノリシックなバックエンドで構成されている場合例え追加でデプロイをする理由がゲームの一部機能であるフレンド機能の拡張であったとしてもサービス全体を入れ替える必要があるでしょう。
- 開発選択肢の壁
    - モノリシックなバックエンド内で複数のプログラミング言語やフレームワークが使われている事は稀でしょう。ゲームの長期運営やチームの拡張によりライブラリやフレームワークを新しい物や全く違う物を採用したい時、モノリスだと全体を変更またはアップデートする必要が出てきます。ゲームはプレーヤーの増加と共に進化させる必要があります。その時々で選べる開発技術が狭まる事でゲームデザインの選択肢を減らしてしまうのは避けたいです。

ではこれらの壁をマイクロサービスでどう回避できるのか確認します。
- スケールの壁
    - マイクロサービスは各々が独立しています。独立したサービスはスケールする際も独立してスケールします。マッチング機能が１つのマイクロサービスであった場合、全体をスケールさせる必要は無くマッチングサービスのみスケールさせる事でコストの最適化に繋がります。
- コケた時の壁
    - マイクロサービス内でエラーが起きた時他のマイクロサービスに影響が出ない保証は確かにありません、ですがエラーの起源を突き止めるのは容易でしょう。より独立したマイクロサービスを作る事でサービス全体を停止させる事は避けられます。
- デプロイの壁
    - デプロイをマイクロサービス単位でできるのはマイクロサービスアーキテクチャの大きな強みです。例えばフレンド機能の拡張や細かな修正のみであればバトルやガチャといった他サービスの影響を最小限に単独で行う事が可能です。
- 開発選択肢の壁
    - ゲームの機能によっては全く別の技術によってスムーズに開発できる物も多いです。例えば追加機能であるリーダーボードにRedisを使いたいが既存のプログラミング言語だとRedis最新版に対応したモダンなライブラリが無い場合でも、リーダーボード管理のマイクロサービスのみプログラミング言語やフレームワークを変更する事でよりスムーズに開発できるでしょう。

と色々書きましたが要約すると、
- ゆとりを持ってゲームを修正、成長させられる
- 需要とゲームデザインに合わせてスケールしやすくなる
- 進化していくゲームにあったテクノロジーを選べる
- ゲームが止まらなくなる

といった事がゲームのバックエンドにマイクロサービスを採用するメリットとなります。
# ゲームにマイクロサービスが向いていないはずがない
上記の例の話を読んでいると見えてきた方もいると思います。そもそもゲームの特徴としてマイクロサービスの構成や考え方と当てはまるポイントが多いのです。

マイクロサービスの開発の大きな課題として上がるのがマイクロサービスのサイズや分け方を考えるスコーピングです。一般的にスコーピングする際はビジネス要件や技術性能を軸に考える事が多いです。このスコピーングという作業に時間をかけ、できるだけ構成を練り直すような事が無いようにするというのは容易ではありません。
ですがゲームはすでに中心にあるバトルやパズルを軸に機能として明確に分かれているのです。ゲームの機能として思いつく物を羅列してみましょう。
- フレンド機能
- ギルド機能
- アチーブメント機能
- ランキング機能
- ストア機能
- インベントリー機能

いかがでしょう、まるでマイクロサービスのサービス名を羅列しているようじゃないですか？一般的に意識される１つのマイクロサービスは１つの機能を持ち独立しているという条件も上記の各機能を見ていると達成できる気がします。やはりゲームにマイクロサービスが向いてないはずがないのです。
# 独立したマイクロサービスを作るコツ
ここまで読んでいる方はもうゲームのバックエンドでマイクロサービスを採用してみようと思っているでしょう。ここでスコーピングという大きな課題をゲームの機能別に分ける事で簡単に乗り越えた皆さんに独立したマイクロサービスを目指す上で参考になるコツをいくつかお伝えします。
### データベースを機能別に考えて選んでみましょう
今までマイクロサービスを意識する事無くゲーム開発を行って来た方はきっと”今回のゲームのメイン DB はこれだ！”でデータベース選定を終えていたと思います。特に、ゲームがどのように拡張されるのか、ゲームデザインが定まっていない初期に決定するとなると”MySQL だと色々クエリーで解消できるし今回も MySQL で行こう！”と決断される方も多いと思います。もちろん MySQL はとても強力であり、MySQL を選定する事やゲームのコアな部分のデータベースを一本化する事はとても自然な事です。しかし、上に書いたようにモノリスの壁をできるだけ避け、スケールする、デザインにあったテクノロジーを選べる、止まらないゲームを開発するにはデータベースを分ける事を最初に意識する事で自然とマイクロサービスを構築できるようになってきます。
#### でた、Amazon DynamoDB 使えって言うんでしょ？
著者である僕の事をよく知っている人は、また DynamoDB を使えと言っていると思っているでしょう。あっています、ですが正確には違います。DynamoDB に向いている所が無いか、１つのゲームの中でも機能別に考えてみる事が大事なのです。もし機能の特徴と DynamoDB の相性がいい場合、例えそれが巨大なゲームの一部分であったとしてもその部分は独立し、DynamoDB のメリットであるシャーディング・インスタンス管理・チューニングといった面倒な作業からの解放に繋がり、ニーズに合わせ自動的にスケールするフルマネージドなサーバーレスデータベースというアドバンテージを最大限に有効活用しゲームを成長させる事ができるのです。
### 非同期でいいじゃない！
ゲームは非同期で処理を行う事ができる機能が多いのも特徴の１つです。例えばフレンド系のリクエスト処理でフレンド申請やフレンド承認といったリクエストは相手プレーヤーに対して同期的に情報を伝える必要は無く非同期で十分機能の要求を満たします。他にもアイテム入手や新しいクエストの開放にしても、開放の瞬間と利用の瞬間に時差が生まれる事から演出やエフェクトを挟む事で非同期処理を行う事が可能な部分は多々あります。一見マイクロサービスにする事で一部分に非同期処理を強制されるとネガティブに考えがちですが、寧ろゲームにおいてはその非同期処理こそが向いているケースが多いのも事実です。

独立したマイクロサービスを作る上でマイクロサービスをまたいだトランザクションを持つ事に難しさを感じる方は多いでしょう。[AWS for Games Advent Calendar 2022](https://qiita.com/advent-calendar/2022/aws-for-games)　の9日目の記事に”マイクロサービスとトランザクション”という記事があります。この課題に対する詳しい対処法の例は是非こちらの記事を参考にしてみて下さい。
# 大丈夫です、すでにできてます！
ここまでの話では、マイクロサービスを今までゲームのバックエンドで意識した事がない方や、初めてマイクロサービスを知る方には少し敷居が高く感じられたかもしれません。しかし、今までゲームを開発した事ある人の中にはすでに無意識にマイクロサービスを採用、もしくはマイクロサービス的考え方を行っている開発者も多いのです。前述した通りゲームは機能別にすでにマイクロサービスのような構成をしています、モノリスを意識していたとしても１つのサービスの中ですでにモジュールとして分かれている事もあるでしょう。いくつかマイクロサービス的考え方をすでに行っている例を挙げましょう。
### リーダーボードの構築
ゲームには必須な機能になりつつあるリーダーボード、開発を行った事ある方も多いでしょう。そんなリーダーボードですが”データベースを機能別に考えて選ぶ”という点では多くの開発者がすでに実行していると言えます。リーダーボードのデータベースとしてよく採用されるのが Redis です。Redis の Sorted Sets がもつ `ZADD` や `ZRANGE` といったコマンドはとても強力で簡単にスコアをソートさせ任意の順位を取得できます。この事から多くの開発者がすでにリーダーボード向けにデータベースを分けマイクロに管理しているでしょう。
### マッチング機能の構築
マルチプレイヤーゲームには欠かせないマッチング機能、ここでも無意識に”データベースを機能別に考えて選ぶ”事や”非同期で処理”といった事を行っている開発者は少なくないでしょう。マッチング機能のデータベース選定で大事になってくるのはマッチング条件であり、その条件が複雑で強い整合性が求められる場合 MySQL など複雑なクエリーを得意としたデータベースを選び、反対に強い整合性が必要の無いマッチングだと　OpenSearch　などのより柔軟なクエリーを得意としたデータベースを選ぶでしょう。非同期という観点で見てもマッチング機能はマッチング開始のリクエストとマッチング完了のレスポンスは必然的に非同期になる特徴を持っているので、自然と非同期な他サービスから処理が分離された物を作る事になります。
# できる事からやってみましょう！
最後に、ここまで読んで頂きありがとうございます。読んで頂いたあなたの業務内容や開発者としての立場次第では、いざマイクロサービスを採用するとなってもアプローチの仕方が異なると思います。
#### インフラを管理されている開発者の方々
ゲーム全体では無く、ゲーム内のどの機能にどのデータベースが向いているか考える事から始めてみましょう。AWS にある沢山のデータベースサービスを知る事でゲームの開発の幅が広がるでしょう。
#### バックエンドのコードを書く事がメインの開発者の方々
AWS Lambda など沢山のサーバーレスサービスだけでマイクロサービスの構築は可能です。AWS CDK などを駆使し小さなマイクロサービスを構築してみましょう。小さな機能のほうが非同期処理に挑戦しやすいです、改めて非同期で処理できる物が無いか振り返ってみましょう。
#### 開発チームの中でも決定権を持たれる方々
チームのサイズを考慮しマイクロサービスの開発に向けたチーム構成を考え直してみましょう。１つのサービスを１つのチームにするのもいいですし、複数のサービスを１つのチームで管理するのも各サービスの担当者などを決める事でスムーズにできます。

それでも普段の業務は変わらないと考えられている方も、是非今日から続く[AWS for Games Advent Calendar 2022](https://qiita.com/advent-calendar/2022/aws-for-games) を追いかけながらゲーム開発に使える様々な見解を集めて下さい、新しい事を考える事はとても楽しい事です！では、良いお年を。

(免責) 本記事の内容はあくまでも個人の意見であり、所属する企業や団体は関係ございません。