ビデオゲームのバックエンドデザインの改善に取り組んでいます。ゲームはライブで正常に動作していますが、さまざまな点を改善したいと考えています。ビデオゲームスタジオとして、イベントのライブ中にいじくり回す必要があるイベントを頻繁に行っています。プレーヤーを強制的に更新しなくても、シームレスにこれらの変更を行えるようにしたいと考えています。
現在のバックエンドは、エンドポイントが使用するさまざまなハードコードされた値を使用しています。つまり、エンドポイントの動作を変更したい場合は、再デプロイする必要があります。たとえば、特定のオンラインストアアイテムが別のものを指す必要があると判断した場合、エンドポイントで参照されるIDを変更する必要があります。これは扱いにくく、理想的ではありません。より動的な設定変更方法が必要です。
私たちが持っていた一般的な考えは、これらのプロパティをS3/CDN上のファイルに保存し、クライアントとバックエンドがこれらを定期的にフェッチするというものです。このアプローチには、バックエンドとクライアントの両方が同じ構成を使用することを保証することに関して問題があります。
明確にするための編集されたソリューション
ソリューションA)
「最も信頼できる」ファイルのソースがサーバーと通信できるようにするAPIを作成します。変更があるたびに、この新しいファイルをサーバーのキャッシュにプッシュします。次に、クライアントがサーバーと通信するたびに、クライアントのファイルバージョン/ハッシュを確認し、それを現在のものと比較します。一致する場合は続行します。それ以外の場合は、1)クライアントを強制的に更新する、2)クライアントに手動で更新するよう指示する(つまり、それまではアクセスを拒否する)、または3)クライアントに十分な時間を与えるバージョンの余裕がある理論的には更新。
長所
短所
ソリューションB)クライアントとサーバーの両方が定期的に呼び出しを行い、新しい構成があるかどうかを確認します。クライアントがサーバーと通信し、バージョンが一致しない場合、3つのオプションが再び利用できます。今回のみ、サーバーはストレージ(最も信頼できるソース)を呼び出して、どちらのバージョンが正しいかを確認する必要があります。
長所
短所
ストレージに関する注意S3とCDNの両方に問題があります。 S3は常に正直であるとは限りません-それは時々古いデータを返すことができます-それは真実の単一の情報源ではありません。 CDNはクライアントが特定の言語でこのデータをダウンロードするので便利ですが、新しいバージョンを再配布するたびに時間がかかる可能性があるため、余裕が必要になる場合があります。
これは、私たちの考えの簡単な概要です。概説されている場合とされていない場合のある注意事項がありますが、この種の事柄が通常どのように処理されるかを探しています。
tl; dr:コンテンツを改訂するときは、ファイル名を改訂します。
私たちが持っていた一般的な考えは、これらのプロパティをS3/CDN上のファイルに格納し、クライアントとバックエンドがこれらを定期的にフェッチすることです。
いいえ、あなたが引用する懸念のため、これは間違った設計です。
「the設定ファイルを操作する」クライアントコードについての話し合いがあるかもしれませんが、問題ありません。しかし、あなたの設定にとって重要なのは、 "the"設定ファイルの[〜#〜] uri [〜#〜]は、変更するたびに変更する必要があることです。これにより、キャッシュミスが発生し、クライアントは必要に応じてサーバーと正確に同期します。キャッシュ階層には多くのレベルがあり、そのうちのいくつかは表示または制御できます。新しいURIを作成すると、すべてのレベルでキャッシュミスが発生するという素晴らしい効果があります。
これは、ISO8601タイムスタンプとシリアル番号または構成ファイルのURIへのハッシュを追加するという単純な問題です。
構成がチャーンする頻度に応じて、CDNから古いバージョンを期限切れにすることができます。
サーバーは、Kが少なくとも2であるKの最近の構成ファイルに対応する要求を受け入れる必要があります。クライアント要求は、クライアントが使用している構成ファイルを記述して、サーバーが適切な要求であることを確認できるようにする必要があります。
編集:最近、ダイアグラムAとBを追加しました。(A)で、サーバーから「同じファイル」を更新するクライアントを提案します。中間の「透過的」キャッシュがその配置を混乱させる可能性があることを示唆しています。これは、時々クライアントに新しい構成ファイル名を通知して、キャッシュミスを被り、サーバーから取得できるようにするのが適切です。 (B)では、キャッシュの影響をさらに制御することができないため、言及した「S3からの古いデータ」の問題に対処するために、新しい構成ファイル名を作成することはさらに重要です。概要は、各ファイル名でコンテンツを1回だけ公開し、コンテンツを改訂するときにファイル名を改訂することです。そうすることで、Paxos/ZKのような重量のあるアプローチを回避できます。時間t0で新しいリビジョンをプッシュし、サーバーがコピーを取得するまでN秒待つだけです。その後、t0 + Nの後、サーバーはクライアントに新しい名前を自由に送信して、クライアントがそれを使用できるようにします。これにより、ほんの少しの労力で一貫性が得られます。または、ロードバランサーが特定のクライアントを単一のサーバーにハッシュすると仮定すると、すべてのサーバーが新しい構成を取得するのにかかる短い時間内に、クライアントは単一のサーバーとのみ通信するため、簡単にそのサーバーと同期します。
まず、簡単なもの。エンドポイントにHTTPを使用していると思います。クライアントに最新バージョンのリソースがあるかどうかを判断し、更新された場合にのみ条件付きでリソースを取得するための標準化されたヘッダー( 最終更新 、 ETag )があります。ホイールを再発明せずに、構成(リソース)がいつ変更されたかを判別するためにこれらの既存のメカニズムの1つを使用することをお勧めします。 J_Hの回答で提案されているように構成の複数のバージョンを返すことができるようにしたい場合は、それらの構成リソースへのURLで使用可能なバージョンをリストする応答を作成できます。このスキームでは、(一般に)構成を変更せず、代わりに必要に応じて新しい構成を追加して、単にディレクトリを更新します。ヘッダーを使用して、ディレクトリが変更されたかどうかを確認できます。
さて、難しい部分です。 CAP Theorm に慣れる必要があります。これは要約版です:Consistency
、Availabilty
、Partition Tolerance
:最大2つです。ここであなたが尋ねていることの多くはそれに関連しています。
更新を受け取った瞬間に、どのように発信要求を処理するのですか?
この質問は、答える必要がある質問の中心にあると思います。更新する1分前に構成を取得するクライアントがあるとしましょう。秒はどうですか?ミリ秒はどうですか?更新される前にクライアントが数ナノ秒のリソースを取得しても問題ない場合、更新中に古いバージョンを取得しても問題ないでしょうか?私はノーだと思います、そしてあなたがリクエストを満たし始めた時に最新だったバージョンを返すだけです。
ここには本当に2つのオプションがあります。ポーリング:定期的にリソースを定期的にチェックすること、またはイベント:クライアントにメッセージをプッシュして更新があることを通知することです。私の経験では、前者は後者よりもはるかに簡単で堅牢です。また、Pushした場合でも、リソースを更新するタイミングと、リソースを取得するタイミングとの間で、制御できないラグがあります。要するに、設計がサーバーの背後にあるクライアントをしばらく許容できない場合、実装することは不可能です。
最終的には、クライアントを待機させる期間を決定する必要があります。次に、その時間をとり、ポーリング間隔の半分にして開始点とします。頻度が高すぎる場合は、WebSocketなどを確認することをお勧めします。
同じ方法でサーバーとクライアントに構成を配布するという点では、それに触れるタイミングに関していくつかの課題が生じると思います。代わりに、サーバーへの構成の配布には、クライアントへの配布とは異なるプロセスを使用することになるでしょう。いずれにしてもサーバーには異なる情報が必要だと思いますが、知るには十分な詳細情報がありません。これに取り組むことができる1つの方法は、 Zookeeper などの分散DBを介してすべてのサーバーに構成を配布することです。各サーバーに、分散データベース内の構成のバージョンを追跡させることができます。それらがすべて最新の状態になったら、それをCDNに配布し、クライアントに取得させます。これにより、クライアントがサーバーよりも優先されることはありません。
クライアントとサーバーに同じ方法で配布したい場合は、クライアントとサーバーに、使用する構成のバージョンをネゴシエートさせることもできます。これは、Minecraftがクライアントソフトウェアのバージョンを管理する方法や、サーバーがサポートできるバージョンに似ています。基本的に、サーバーはサポート可能なバージョンを提示し、クライアントはそのセットから1つを選択します。この場合、常に両方がサポートする最新のものにしたいようですが、必須ではありません。