マルチプレイヤーのサーバーレス マッチメイキング

この記事では、GitHub のこのサンプルで使用されているアーキテクチャについて説明します。 このリファレンス アーキテクチャのコードはガイダンスの例にすぎず、運用環境で使用するにはコードの最適化が必要な場合があることに注意してください。

MAzure Cache for Redis と Azure Functions を使用するマッチメイキング

関連するサービス

  • Azure Traffic Manager - 待機時間に基づいて、最も適したリージョンのゾーンにプレイヤーを接続するので、選択されています。
  • Azure Functions - 小規模なマッチメイキング ロジックを実行するための最も簡単な方法なので、選択されています。また、マッチメイクしてプレイしようとしているユーザーがいる場合にのみ課金されます。
  • Azure Event Hubs - 要求をバッチ化でき、Azure Cache for Redis の接続プールが使い果たされないようにするのに便利です。
  • Azure Cache for Redis - マルチプレイヤー セッションに参加しようとしているさまざまなプレイヤーの情報と、使用されているゲーム サーバーからの接続情報 (IP/ポート) を格納するための、簡単なキー/値ペアのデータベース。 クエリの柔軟性、インデックス作成、レプリケーション、およびデータの移動が厳密な要件ではないこと、および価格が記憶域容量にのみ基づくことから、選択されています。
  • リソース グループ - Azure Traffic Manager に対して 1 つのリソース グループを使用し、各マッチメイキング リージョン ハンドラーに対して 1 つのリソース グループを使用します (たとえば、北米に 1 つ、ヨーロッパに 1 つ、LATAM に 1 つ、アジアに 1 つなど)。

デプロイ テンプレート

プロジェクトを Azure サブスクリプションにデプロイするには、次のボタンをクリックします。

この操作を実行すると、Azure サブスクリプションに対する azuredeploy.json ARM テンプレート ファイルのテンプレート デプロイがトリガーされ、必要な Azure リソースが作成されます。 これにより、Azure アカウントの料金が発生する場合があります。

Azure サービスの名前付け規則と制限事項をまとめたセクションが含まれる一般的なガイドライン ドキュメントを参照してください。

注意

ARM テンプレートの動作に興味がある場合は、このリファレンス アーキテクチャで利用されている各サービスの Azure Resource Manager テンプレートのドキュメントを参照してください。

最後に、関数のアプリケーション設定を追加して、サンプル プロジェクトが Azure サービスに接続できるようにします。

  • EVENTHUB_CONNECTION_STRING - 作成された Azure Event Hub 名前空間への接続文字列
  • REDIS_CONNECTION_STRING - 作成された Azure Cache for Redis への接続文字列

ヒント

Azure Functions をローカル環境で実行するには、local.settings.json ファイルをこれらの同じアプリ設定で更新します。

ステップ バイ ステップの手順

  1. プレイヤーのクライアント デバイスは、トラフィック マネージャーに接続し、プレイヤーをマッチメイキング キューに追加する要求をルーティングします。
  2. トラフィック マネージャーは、待機時間が最も短いリージョンのゾーンに接続し、要求をキャプチャしてバッチで処理できる Azure Event Hub をポイントします。
  3. Event Hub は、マッチメイキング プールに追加される新しいプレイヤーの詳細を、プレイヤーの追加 Azure 関数に渡します。
  4. この Azure 関数は、最初に、ポーリング メカニズムによってゲーム サーバーの接続の詳細をプレイヤーに提供するためのエンドポイントを公開するマッチ要求永続 Azure 関数オーケストレーターを作成します。 マッチメイキング要求ごとに 1 つのオーケストレーターがあり、オーケストレーターのオーケストレーション インスタンス ID は、後でプレイヤーにイベントを送信できるようにプレイヤーの GUID にする必要があります。
  5. 次に、同じ Azure 関数によって、プレイヤーがデータベースに追加され、プレイヤーは適切な既存のゲーム セッションにも含められます。使用できるゲーム セッションがない場合は作成されます。
  6. その後、ポーリング メカニズムにおいて、プレイヤーのクライアント デバイスはトラフィック マネージャーに接続し、プレイヤーにゲーム セッションの接続の詳細を提供する要求をルーティングします。
  7. トラフィック マネージャーは、前述の Azure 関数 (ステップ 4) をポイントします。
  8. その Azure 関数は、タイムアウトのためのタイマーを作成した後、ゲーム セッション サーバー接続の詳細 (IP:ポート) が含まれるイベントまたはタイムアウト イベントのどちらか早いほうを待機します。
  9. 準備完了セッション タイマー トリガー済み Azure 関数は、データベースをスキャンして、マッチを開始するのに十分なプレイヤーがいるセッションを取得します。
  10. また、サーバー接続の詳細 (IP:ポート) をフェッチして使用可能なサーバーを検索し、使用可能なサーバーの一覧からそのサーバーを削除します。
  11. 開始する準備ができている各ゲーム セッションについて、準備完了セッション タイマー トリガー済み Azure 関数によってプレイヤーのリストがフェッチされ、サーバー接続の詳細と共に Azure Event Hub に情報が渡されます。
  12. この Azure Event Hub は、マッチメイク済み通知ディストリビューター Azure 関数にフィードします。
  13. この Azure 関数は、Azure Event Hub のメッセージを使用し、プレイヤーの GUID をオーケストレーター インスタンス ID として使用して、各プレイヤーのマッチ要求永続 Azure 関数オーケストレーター (ステップ 6) に到達します。
  14. クライアント デバイスは、接続先のサーバー接続の詳細 (IP:ポート) を受け取り、ゲーム サーバーに直接接続します。 マッチメイキングの試みがタイムアウトした場合、クライアント デバイスはそれを正常に処理します。

実装の詳細

マッチ要求モニター (マッチ要求ごとに 1 つ)

プレイヤーは、ゲームに接続したいときは、マッチ要求永続 Azure 関数オーケストレーターを開始します。それは次のことを行います。

  1. 要求のタイムアウト期間に対して CreateTimer を呼び出します。
  2. WaitForExternalEvent を呼び出してサーバー準備完了イベントを待機します。そのイベントには、サーバーの情報が含まれます (マッチメイク済み通知ディストリビューター Azure 関数を参照)。
  3. Task.WhenAny を使用して、最初のタスクから戻るのを待機します (1 または 2)。
  4. サーバー準備完了イベントが到着する前にタイムアウトが発生した場合は、クライアント デバイスが理解する何らかのエラー メッセージを返します。
  5. タイムアウト前にサーバー準備完了イベントが到着した場合:
    • タイムアウト タイマーを取り消します。
    • サーバーの情報を返します。

注: ゲームのオーケストレーション インスタンス ID は、プレイヤー ID であるか、または a) クライアント デバイスで保持されていて、b) Azure Cache for Redis に格納されている、要求に対する他の一意の識別子である必要があります。

バッチ処理準備完了セッション モニター (タイマー トリガー済み Azure 関数)

これは、Azure 関数アプリの起動時に開始されます。

  1. Azure Cache for Redis ですべての準備完了セッションをクエリします。
  2. 準備完了セッションごとに、サーバー準備完了通知を送信します。

マッチメイク済み通知ディストリビューター Azure 関数

"サーバー準備完了" 通知を使用する通知システム トリガー済み Azure 関数 (非永続的) では、次のことが行われます。

  1. マッチメイク済み通知ディストリビューター Azure 関数に要求を送信します。
  2. マッチ要求永続 Azure 関数オーケストレーターを使用して、サーバー準備完了イベントをセッション内の各プレイヤーに送信します。
    • プレイヤー ID に一致するオーケストレーター インスタンス ID に送信します。特定のオーケストレーション インスタンス ID の使用は、この関数がイベントの送信場所を認識する方法です。
    • サーバー情報を送信します。

クライアント デバイスは、マッチ要求モニターの状態をポーリングし、オーケストレーションが進行中であること、あるいは a) タイムアウト メッセージまたは b) サーバー情報で完了していることを確認します。 b の場合は、サーバーに接続します。 特にこのシナリオでは、クライアント デバイスによって呼び出される必要がある GET URL は次のようになります。 GET /runtime/webhooks/durabletask/instances/{playerGUID}?code={systemKey}

読者のための演習

提供されているサンプルには、プレイヤーが進行中のマッチメイキング要求をキャンセルすることにした場合を処理するロジックが含まれていません。 そのシナリオでは、後でマッチメイキングを試行できるように、プレイヤーをデータベースから削除する必要があります。

PlayersTimeStartedMatchmaking および SessionsCreationTime の並べ替えセットを使用しないので、マッチメイキング時間を最適化するために利用できます。

また、可能な限り汎用的にするため、サンプルには使用できるサーバーがない場合にスケールアウト要求を行うコードは含まれていません。 バッチ処理準備完了セッション モニターのタイマー トリガー済み Azure 関数内にはキューがあります。

データベースのセットアップ

名前 Redis の種類 詳細 Redis コマンドのサンプル
Servers Redis ハッシュ サーバーの情報を格納します hmset Servers GUID "IP:Port" GUID "IP:Port"
ServersAvailable Redis セット 使用可能でゲーム セッションをホストできるサーバーの GUID を格納します sadd ServersAvailable "GUID"
Player Redis ハッシュ プレイヤーの情報を格納します hmset Player:GUID Name "value1" MatchmakingSettings "value2"
PlayersTimeStartedMatchmaking Redis 並べ替え済みセット プレイヤーがマッチの検索を始めた日付を格納します。 キーはプレイヤーの GUID、値は日付の UNIX タイムスタンプです。 zadd PlayersTimeStartedMatchmaking GUID TIMESTAMP
Session Redis ハッシュ 容量やマッチメイキング バケットなど、ゲーム セッションの情報を格納します hmset Session:GUID Capacity value1 MatchmakingSettings value2
SessionsPerMatchmaking Redis セット マッチメイキング バケットごとのセッションを格納します sadd SessionsPerMatchmaking:MatchmakingBucket "GUID"
SessionPlayers Redis セット ゲーム セッションからのプレイヤー識別子を格納します sadd SessionPlayers:SESSIONGUID "PLAYERGUID"
SessionsReady Redis セット 容量が 0 のすべてのセッションを格納します。これは、ゲーム サーバーが利用可能になるとすぐに開始できることを意味します。 sadd SessionsReady "GUID"
SessionsCreationTime Redis 並べ替え済みセット 各ゲーム セッションが初期化された日付を格納します zadd SessionsCreationTime GUID TIMESTAMP

スケーリング

Azure Cache for Redis の容量については、「Azure Cache for Redis のスケーリング方法」を参照して、マッチメイキング情報を格納するデータベースを適切にスケーリングする方法を確認してください。

Azure Event Hub の特性と、パーティション カウントのモデル化に関する経験則については、一般的なガイドラインのドキュメントを参照してください。

その他のリソースとサンプル

Azure Event Hubs SDK for Unity: これはサンドボックス プロジェクトです。 この記事の内容はサポートされていないため、古いか、動作しない可能性があります。

価格設定

Azure サブスクリプションをお持ちでない場合は、無料アカウント を作成して 12 か月間の無料サービスの利用を開始できます。 それらのサービスの制限を超えない限り、Azure 無料アカウントで無償で提供されているサービスに対して料金が発生することはありません。 Azure Portal または使用状況ファイルを通じて使用状況を確認する方法について説明します。

これらのリファレンス アーキテクチャの実行中に使用される Azure サービスのコストはユーザーが負担し、その合計は分析パイプラインで実行されるイベントの数によって異なります。 リファレンス アーキテクチャで使用されていた各サービスの価格は、Web ページで確認ください。

また、Azure の料金計算ツールを使用して、使用する予定の Azure サービスのコストを構成および見積もることもできます。