MMOで負荷分散はどのように達成されますか?


26

負荷を軽減するために、単一のシャードまたはレルムの処理を複数のサーバーで実行できることがMMOの一般的な要件だと思います。すべてのプレイヤーとすべてのNPCが相互作用できる統一された一貫した世界を維持しながら、これをどのように行うことができるのか興味があります。

私の質問は、MMOでロードバランシングをどのように達成するかです。

このテーマに関する知識を向上させる方法に関するリンク、書籍、または一般情報も歓迎します。

回答:


30

これをできるだけシンプルに保ち、インターフェイスを適切に定義して文書化してください。実稼働環境で複雑なシステムを保守およびデバッグすると、簡単に地獄になります。したがって、単純なアプローチと複雑なアプローチがある場合は、複雑なアプローチに進む前によく考えてください。

サービスの定義

最初のステップは、静的コンテンツ、認証、ローカルチャット、グローバルチャットチャネル、リージョナルチャットチャネル、フレンドリスト、ギルド、バッグ/インベントリ、オークションハウス、グローバルマップ、ワールドなどのサービスとその依存関係特定することだと思います。

次に、これらの各サービスについて、クライアントが直接サービスにアクセスできるかどうかを決定しました。たとえば、クライアントがグローバルチャットチャネルを担当するサーバーと直接対話できるようにするのは非常に簡単です。ワールドサーバーは、チャットメッセージにまったく関与する必要はありません。リージョナルチャットも同じ方法で実装できますが、ワールドサーバーは、プレイヤーがリージョンを変更したときにチャットサーバーに通知する必要があります。繰り返しますが、彼らはメッセージを気にする必要はありません。

3番目のステップは、サービス内の負荷分散について考えることです。たとえば、グローバルおよび地域のチャットチャネルは、名前に基づいて複数のサーバーに分割できます。この分割をクライアントにハードコーディングせずに、ルックアップサービスを提供することをお勧めします。

ワールドサーバー

最も難しい部分は通常、ワールドサーバーです。そのため、単純なアプローチから始めます。クライアントが現在いる地域を担当するサーバーと直接対話できるようにすることをお勧めします。そのため、ログインまたは地域を越えたときに、クライアントが接続するサーバーに通知する必要があります。

簡単なアプローチは、世界を独立した地域に分割することです。独立した地域では、プレイヤーはある部分から別の部分を見ることはできず、モンスターは部分を横切ることができません。これらの地域は、外の世界の風景や物語に基づいてプレイヤーが見る地域とは異なります。通常、ほとんどのモンスターはダンジョンにあり、プレイヤーはダンジョンに入るためにゲートウェイを通り抜けなければならないことを受け入れる傾向があります。特に、これらのダンジョンがプレイヤーグループごとにインスタンス化される場合。外の世界の他の例は、高山に囲まれた異なる大陸と谷です。

連続世界のクライアントのニーズを何情報:それはうまくそれを計画するために理にかなっているようなアプローチは、すぐには本当に複雑になりますか?サーバーはどの情報を共有する必要がありますか?プレイヤーは、ほとんど同じリージョン内のオブジェクト(モンスターやNPCを含む)とのみ対話します。ゾーンの境界線からクリック範囲外にオブジェクトを配置することにより、チートできます。これは、クライアントが隣接ゾーンの読み取り専用情報にほとんど関心があることを意味します。これらの場合、ゾーンサーバーは、プレーヤーが隣接ゾーンに接続するのに十分な距離にあることを確認する許可チェックを除き、何も調整する必要はありません。

これにより、オブジェクトやアクションがサーバーの境界を越えなければならない困難なケース非常に少なくなります。矢印や呪文などの場合はパフォーマンスが重要なので、これは良いことです。戦闘を攻撃と防御に分けるのは良い考えかもしれません。そのため、スペルキャスターのサーバーは、キャスターの位置を含む攻撃パラメーターを定義します。防御側のサーバーは、攻撃に関するメッセージを取得し、影響を計算します。攻撃者のサーバーは影響について知る必要はありません。クライアントは、読み取り専用接続を使用してそれについて学習します。

プレーヤーモデルの複雑さによっては、別のサーバーに転送するのに数秒かかる場合があります(Second Lifeにはこれに大きな問題があります)。この問題は、プレーヤーが仮想境界に近づいたときに事前に転送準備することで軽減できます。そのため、実際のハンドオーバーが発生したときに、ほとんどのプレーヤーデータが宛先サーバーに既にキャッシュされています。

概要

ほとんど依存せずにサーバー間で分割できるさまざまなサービスを定義することにより、問題を分割します。次のステップとして、重要なサービス内で負荷分散を行う方法を調べます。関連するサーバーに直接接続するようにクライアントに指示することにより、クライアントに分散作業を委任します(明らかにサーバーはアクセス許可を確認する必要があります)。できるだけシンプルに保ち、さまざまなサービスとサーバーの責任を文書化し、デバッグ出力を有効にするオプションを提供します。

PS:これらの手法のいくつかは、信頼性を向上させるために使用できます。また、多くのサーバーを使用すると、物事が壊れるリスクがはるかに高くなるため、この点に留意してください。ソフトウェアだけでなく、ハードウェアレベルでもです。


しかし、実際には、このプロセス間通信をどのように行うのですか?どのようなIPCを使用する必要がありますか?
マジダリフ

10

一般的に、世界はいくつかの小さな地域に分割されています。これらの各リージョンは通常、独立したサーバープロセス(WoWのワールドサーバーまたはEveのSolノード)であり、任意の数のマシンで実行できます。一部のゲームでは、マップ間に明示的なドアがあり(イブ、STO、ギルドウォーズ)、他のゲームではこれをさらに隠そうとします(WAR、フリーレルム)よりシームレスなアプローチを選択した場合は、通常、2つのサーバー間の境界に近づいていることを検出し、2つのプロセスがハンドオフをネゴシエートします。おそらくこれの説明を探すのに最適な場所は、セルタワーが移動するハンドセットのハンドオフを行う方法です。1つのマップ(Jita、Ironforge、Earth Space Dock)の負荷が非常に大きくなる場合、個々の機能を他のサーバー(AI、プレーヤー管理の特定の部分)が、これは最初から組み込まれている必要がありますか、いくつかの深刻な改造が必要です。ほとんどの場合、より優れたハードウェアを購入してこれらの少数のマップ専用にする方が、コスト効率が高くなります。


9

負荷を軽減するために、単一のシャードまたはレルムの処理を複数のサーバーで実行できることがMMOの一般的な要件だと思います。すべてのプレイヤーとすべてのNPCが対話できる統一された一貫した世界を維持しながら、これをどのように行うことができるのか興味があります。

おそらくあなたが思うほど一般的ではありません。少なくとも、1つのシームレスな世界が複数のサーバーによって同時に管理されていると考えている場合は別です。

完全に別々のシャードをカウントするのではなく、オンラインゲームを分割できる2つの方向があり、「水平」と「垂直」と見なすことができます。

  • ゲームを多くの別々の地理的領域に分割します。特定の地理的領域のすべての機能は1つのサーバーによって処理され、それらの間の実際の相互作用はありません。(サーバーごとに必ずしも1つのゾーンがあるわけではないことに注意してください。サーバーは複数のゾーンを同時に処理でき、負荷の変化を処理するためにサーバー間でゾーンを転送できます。)
  • ゲームをいくつかのタイプのサービスに分割します-例えば。ログイン/承認、ゲームプレイルールと物理学、チャット+オークション、永続化など。これらの各サービスは、異なるサーバーで処理できます。nhnbの答えは、開発者がゲームを分割できる他の潜在的なサービスを列挙しています。

明らかに、これらのアプローチは直交しており、2つを組み合わせることができます。実際、ゲームプレイとは別のマシンにログイン/認証をプッシュすることは非常に一般的であり、ゲームの世界に関係なくチャットやその他の重要ではない通信をファーム化することは非常に一般的です。分割されます。

しかし、全体として、地理的なパーティションがある場合、ほとんどのゲームでは、うまくやることが難しいため、これらの境界を越えてやり取りすることを避けています。代わりに、他の方法を使用して、実際にはそうではない場合でも、すべてが同じシャードにあり、同じサーバー上にいるように見せます。例えば。-ゾーン間またはある大陸から別の大陸への移行時に、サーバーの変更をカバーするロード画面またはその他のアニメーションが変更されます。-別のダンジョンまたはレイドインスタンスは、他の全員から隔離されています。これらはシャード内のシャードのようなもので、別のサーバーで簡単に実行できるため、負荷分散に役立ちます。

WoWの権威と話すことはできませんが、彼らは上記のほぼすべてを実行していると思います:インスタンス化、相互作用することができない別々の地理的領域、ある種のポータル、別々のバックエンドおよび認証サーバーによって結合されています。WoWレルムでは、特定のレルムで一度に1000〜10000人のプレイヤーがオンラインになります。これは上記のスキームで簡単に管理できます。

しかし、単一の巨大な世界があり、プレイヤーが1つのサーバーに隣接するサーバーのプレイヤーと対話できるようにする必要があると仮定しましょう。これは理論的には簡単です-最初に、サーバーは境界に沿ってオブジェクトの詳細を共有するために協力する必要があります(したがって、1つのサーバー上のオブジェクトは別のプロキシ表現を持つことがあります)。次に、すべてのロジックをメッセージ受け渡しに変更します。必要に応じて、プロキシから信頼できるソースにルーティングされるメッセージ。メッセージはサーバー間またはサーバー内でかなり透過的に渡すことができるため、1つのアプローチがすべてのシステムに適合します。

ここでの問題は、以前は単純なロジックがメッセージに変換されると非常に複雑になる可能性があることです。両方のプレイヤーが1つのサーバー上にいるときに安全かつアトミックに発生する2プレイヤーのトレードは、メッセージを送受信するたびにプロセスが長くなり、送信ごとに再検証し、1人のプレイヤーが悪用できないようにするためのセーフガードを設けますもう1つは、メッセージの移動中に取引を変更することです。メッセージが到着するまでに他のプレーヤーがまだ存在しているとは想定できないため(死んだり、ログアウトしたりする可能性があるため)、コードは非常に複雑になります。そして、これは、取引、戦闘、グループ化、オークション、略奪、トレーニングなど、2つ以上のエンティティが相互作用または協力できるほとんどすべてのシステムに適用されます。

これらの問題は克服できないものではありませんが、ほとんどのゲームでは、他の手段で負荷を共有し、すべてのゲームロジックを1つのサーバーに保持できる場合、試してみる価値はありません。そのため、現在のほとんどすべてのゲームが代わりにそのルートをたどります。


3

MMOサーバーの負荷分散には多くの方法があります。処理されるデータの範囲は非常に広いためです。私はプロセスビンツリー方式を好みます。

グローバルサーバーは、一度に複数のユーザーを処理できるプロセスビンにユーザー接続を渡します。プロセスビンはすべての複雑な処理を行い、グローバルチャットやポジショニングなど、グローバルに関連するデータでグローバルサーバーにのみ応答します。この方法は、リージョンの人口が大きく異なるため、リージョンサーバーよりもはるかに優れたバランスをとりますが、ユーザー処理全体は、ほとんどの部分で自然にバランスが取れるように十分に変化します。

グローバルサーバーを介して基本的な負荷分散を行うだけで、プロセスビンが特定のメモリ/ CPU使用量に達すると、新しいプロセスビンサーバーを起動します。


プロセスビン間で共有されるデータをどのように共有しますか(たとえば、異なるプロセスビン上の2人のユーザー間の戦い)。イベントの順序をどのように保証しますか?そのため、プレイヤーを殺したビンが攻撃を行ったビンよりも遅くても、プレイヤーが倒されてももう攻撃を行うことはできません。グローバルサーバーでディスパッチのオーバーヘッドが高くなるリスクはありますか?ユーザー接続のプロキシモデルは、ネットワークスタックのオペレーティングシステムの制限に達する可能性があります。
ヘンドリックブルーマーマン

このモデルは、ほとんどのトランザクションが分離されている情報システムで非常にうまく機能します。通常、同じデータでは機能せず、まれにロックまたはロールバックが使用されます。しかし、戦いに複数のプレイヤーやクリーチャーが含まれ、攻撃の影響が攻撃者と防御者の両方の属性に影響されるゲームでは、このアプローチは難しいかもしれません。
ヘンドリックブルーマーマン

簡単な方法でマルチユーザーインタラクションをグローバルに関連させるか、プロセスビンが相互に認識して通信するための簡単な方法を作成することができます。各プロセスビンは、一度に約1万人のユーザーを処理できる必要があるため、ユーザー間の状態通信はあまり問題になりません。リージョン方式は少し簡単ですが、バランスがとれていないため、同じリージョンに多くのユーザーが入ると簡単にクラッシュする可能性があります。大規模なユーザーベースのMMORPGでは、負荷を均等に分散することが非常に重要です。
スティーブンベランジャー

2つのプロセスビンが戦闘のようなシステムをネゴシエートできるようにするための「簡単な方法」を知りたいです。問題は低レベルの通信ではありませんが、一般的なゲームプレイアルゴリズムは分散した参加者では非常に複雑になります。
キロタン

私の実装では、グローバルサーバーは接続されているすべてのクライアントのリストを保持し、接続されているプロセスビンを追跡します。プロセスビンが別のユーザーにアクセスする必要がある場合、最初に自分のユーザーリストをチェックします。それが失敗した場合、グローバルリストをチェックし、他のユーザーが接続しているプロセスビンを特定します。その後、プロセスビンは直接​​接続してユーザー状態を共有し、統合処理を行います。
スティーブンベランジャー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.