Open Match 超入門
この記事は Google Cloud Japan Customer Engineer Advent Calendar 2019 の 22日目の記事です。
TL;DR
Open Match はオープンソースのマッチメイクフレームワークで、スケーラブルで拡張性のあるマッチメーカーを簡単に構築することができます。
また、本番環境で大規模に動かす際の多くの課題を取り除きつつ、開発者がどのようにマッチメイクするかをコントロールできるようにデザインされています。
…なのですが、Open Match は専用の用語が多かったり、ちょっと試すのにも実装が必要になるなど、Agones に比べると正直なところとっつきにくく難しいと感じていました(ごめんなさい。。)
しかしながら、Open Match の v0.8.0 でドキュメントが大幅に改善されましたので、これを頼りにまずは超入門として、用語の整理を中心に Open Match を読み解いていこうと思います。
Open Match の用語
まずはこの記事の最大の目的である(個人的に整理したかった)Open Match 固有の用語について書いていきます。
Ticket
マッチをリクエストしたプレイヤー(もしくはプレイヤーグループ)を表す、Open Match における基本的なマッチメイクのエンティティ。
Ticket Pool (Pool, Player Pool)
Ticket
(プレイヤー) を例えば、ゲームモードやランクごとにグルーピング (Pool) するために使われるフィルターのセット。
フィルターの種類としては以下のようなものがある。
- double range (浮動小数の範囲)
- string equals (文字列の一致)
- tag present (タグの有無)
使用例)
Ticket
作成時にTicket
の SearchFields にフィルタしたい (グルーピングしたい) 数値や文字列やタグを設定するMatchProfile
(後述) のPool
を設定する。このPool
がTicket
の SearchFields に対するフィルタのセットになっているMatch Function
(後述) がMatchProfile
を使用してマッチを作成する
MatchProfile
マッチの仕様を表し、プレイヤーを選択する条件を示すのに使われる。
Match Function
がマッチを作成するのに必要となる以下のような情報を持つ。
- プロファイルの名前。作成されたマッチがどのプロファイルから作成されたものかを識別する。
- マッチの対象となる
Ticket
のPool
。各Pool
はプレイヤーがどのPool
に属するかをフィルタするための条件を持つ。 Roster
(オプション) (後述)。名前付きの Tiket ID グループ。
Roster
Ticket ID の名前付きコレクション。マッチの Ticket に所属するチームやそのサブチームなどをラベルづけするために使うことができる。
また、「バックフィル」や「参加中」などマッチの現在の状態を表すのにも使うことができる。
Assignment
Ticket
に対するゲームサーバーの割り当てを表す。
Open Match から Ticket
の作成元に返却される情報で、IP アドレス、ポート番号などゲームサーバーへの接続情報が含まれる。
Open Match のコンポーネント
次に Open Match を構成する/に必要となるコンポーネントについて見ていきます。
コンポーネントの種類としては「Core Components」「Customized Components」「External Components」の 3 つに分けることができます。
Core Components
Kubernetes 上でホストされる一連のサービスで gRPC/HTTP 経由で提供される Open Match のコア機能。
Open Match フロントエンド
Ticket
の作成、削除、現在の状態取得などに使用される、 Tikcet
の管理機能を提供する。
Open Match バックエンド
マッチ作成のコア機能を提供する。 MatchProfile
を受け取り、リクエストされたプロファイルにあったマッチを返す。
MMLogic
Match Function
が state storage から Ticket
をクエリするためのヘルパー API。
Customized Components
Open Match を使用してカスタムのマッチメーカーを構築するために、以下のコンポーネントのカスタマイズが必要になる。
Match Function
マッチメイクロジックのコアとして実装されるコンポーネント。
Open Match バックエンド
はマッチを作成するようリクエストを受けた時、Match Function をトリガする。Match Function は MatchProfile
を受け取り、 MMLogic
からプロファイルにあう Ticket
を取得して、マッチを返却する。
Evaluator
Open Match では同じ Pool
に対して Match Function
を同時に実行することができるため、1 つの Ticket
が複数のマッチに含まれることがある。Evaluator は Match Function
が作成したこの複数のマッチを評価して重複を排除する。
External Components
ゲームサービスにはプレイヤーコネクションの取り扱いや専用ゲームサーバーとの連携など Open Match が提供するマッチメイク以外にもいくつかの機能が必要となる。
以下のサービスは Open Match と連携してゲーム特有のマッチメイクを実現するもので、Open Match には含まれないが、マッチメイクサービスの一部になるものである。
Game フロントエンド
ゲームクライアントからのマッチメイクリクエストを受け取り、 Assignment
を返す。
Game フロントエンドではプレイヤーの認証、(プラットフォームサービスから)プレイヤーデータの取得などを行い、 Ticket
の作成を通じて Open Match にマッチメイクのリクエストを行う。
また、作成した Ticket
の Assignment
のセットを確認し、セットされた際はこれをゲームクライアントに返す。
Director
Open Match から MatchProfile
(のセット)にあうマッチを取得し、そのマッチで使用するゲームサーバーをゲームサーバーのアロケーションシステム(例えば Agones の Allocator Service)から取得する。
取得したゲームサーバーの情報(ゲームサーバーへの接続情報)から Open Match バックエンド
を通じて Assignments
を作成する。
マッチメイクの流れ
Open Match を構成するコンポーネントや用語がわかったので、マッチメイクがどのように行われるのか、各コンポーネント同士がどのようなやりとりをするのか、その流れをみてみましょう。
Open Match でのマッチメイクは大きく「マッチメイクリクエスト」「マッチの作成」「Assignment のセット」に分けられます。
マッチメイクリクエスト
- ゲームクライアントはマッチを見つけるために
Game フロントエンド
に接続してAssignment
を要求 Game フロントエンド
はプレイヤーを検証。問題なければプレイヤー情報を(プラットフォームのサービスなどから)取得し、Open Match フロントエンド
をコールしてこのプレイヤーのTicket
を作成
この段階で、プレイヤーを表す Ticket
が( Ticket Pool
の一部として)作成され、Open Match によるマッチメイクの対象となります。
マッチの作成
Director
はMatchProfile
にあったマッチを作成するよう、定期的にOpen Match バックエンド
のFetchMatches
をコールOpen Match バックエンド
のFetchMatches
はMatch Function
を実行Match Function
は Open Match Data Access API (MMLogic
) を通じて、MatchProfile
に設定されているPool
から、一致する全てのTicket
を取得Match Function
は取得したTicket
からマッチを作成Open Match バックエンド
は作成したマッチをDirector
に返す
Assignment のセット
Director
はマッチに使うゲームサーバーのアロケーション(ゲームサーバーの確保と IP アドレス、ポート番号などの接続情報の取得)を専用ゲームサーバーにリクエストDirector
はアロケートしたゲームサーバーへの接続情報を含むAssignment
を作成Director
は全てのTicket
に、作成したAssignment
をセットするためOpen Match バックエンド
のSetAssignment
をコール
これによってTicket
のAssignment
が Open Match の State Store(デフォルトは Redis)にストアされるGame フロントエンド
はOpen Match フロントエンド
からAssignment
を取得してゲームクライアントに返す- ゲームクライアントは
Assignment
内の接続情報を使用して、ゲームサーバーに接続しゲームを開始する
おわりに
Open Match はどのようなコンポーネントから構成されるのか、Open Match 固有の用語が何を表しているのかを中心に読み解いてきました。
記事中でも軽く触れましたが、実際に Open Match を使うためには Game フロントエンド
, Director
, Match Function
あたりをカスタマイズしたり、自分で実装したりする必要があります。また、 Ticket
や Assignment
の具体的なフォーマットや Agones と連携するにはどうしたらよいかも気になるところです。
これらについてもドキュメントを読み解きながら記事にできたらいいなぁと思っています。…つづく(かも)