個人的なプロジェクトとして、MMOをセットアップし、サーバーをC#/。NET Coreで作成しています。
現在のところ、私のアーキテクチャは次のとおりです。世界にはさまざまなエリアが存在します(ポータルからエリアにエリア間を移動できます)。サーバー上のエリアは「部屋」と呼ばれます。各部屋には、独自のクライアントのリストがあります(各プレイヤーにはTCP stream)が付いています)。
今、私は各部屋をそれ自身のスレッドで実行するのは大丈夫かと思っていました。各部屋は、他の部屋から独立しているため、独自の更新サイクル(ゲームループ/部屋)を管理します。
私の心配は、ゲームが成長するにつれ、多くの領域を取得し、領域ごとのスレッドはそれほど素晴らしいアイデアではないということです。
だから私の質問は:私は将来、何か間違ったことや非有益なことをしていますか?すべての部屋のゲームロジック用に1つのスレッドを用意した方がいいですか?または、部屋ごとにスレッドがあっても大丈夫ですか?
ゲームルームを異なるスレッドに分離することから始めるのが良いでしょう。それを超えることをお勧めします。部屋間で共有されるデータ量はどのくらいですか?データがほとんど共有されていない場合は、部屋間でデータを共有するための内部API(サービスコールや共有データベースなど)を設計し、各部屋を個別のプロセスにすることができます。これにより、異なるマシンでのホスティングルームが容易になります。
おそらく、各部屋は独自のエンドポイント(IPアドレス+ポート)でリッスンできます。プレイヤーが部屋に入るポータルに入るとき[〜#〜] a [〜#〜]部屋に行く[〜#〜] b [〜#〜]:プロセス[〜#〜] a [〜#〜]プレーヤーオブジェクトに処理を渡す[〜#〜] b [〜#〜]内部APIとチャネルを介して同時にプレーヤーのゲームクライアントが、プロセス[〜#〜] b [〜#〜]がリッスンしているエンドポイントへの新しい接続を開きます。
スレッドを使用して、部屋内の同時実行性を強化できます。ゲームクライアントとの通信は、メインゲームループとは別に、スレッドのプールで処理できます。物理学は独自のスレッドを持つことができます。 AIは独自のスレッドを持つことができます。
これは実行可能なアーキテクチャかもしれません。マルチスレッドアプリケーションのバグの最大の原因は、データへの共有アクセスです。したがって、部屋が互いにほとんどまたはまったく通信せず、部屋が明示的に所有していないデータにアクセスする必要がほとんどない場合は、並列化のユニットの明白な候補のように見えます。
並列化が多すぎることが心配な場合は、通常、スレッド化を減らす方が、スレッド化を増やすより簡単です。結局のところ、部屋を順次処理したい場合は、通常、更新メソッドを変更して、複数の部屋を1つだけではなくループで処理するように変更することは、ほとんどリファクタリングの労力ではありません。一方、シングルスレッドアーキテクチャをマルチスレッドアーキテクチャに細分化すると、すぐにバグの多い混乱に陥る可能性があります。
ちなみに、コードを ThreadPool
クラスを中心に編成し、Task
sをそのクラスに渡すと、各タスクは、シングルルーム。 ThreadPool 設定可能 特定の数のスレッドを使用します。 (仮想)CPUコアの数よりも多く設定しないでください。スレッドよりも多くのタスクを指定すると、それらのタスクは、スレッドが終了するとすぐにキューに入れられて処理されます。つまり、更新のスケジュールをフレームワークに任せることができます。
マルチスレッドに関する重要な事実:
アーキテクチャの影響:
代替案:
あなたのマルチスレッドアプローチは非常に良いスタートです。ただし、各部屋にスレッドを割り当てる代わりに、複数の部屋を管理するスレッドを用意することもできます。構成で決定するか、実行時に動的に計算できる数。
もう1つの質問は、I/Oの管理方法です。ルームはユーザー接続を管理していますか?いいえの場合は、I/Oにより多くのスレッドを割り当て、それをキューベースのアーキテクチャで分離することをお勧めします。
最後に、マルチスレッドルームの問題は、サーバーを超えて拡張できないことです 現実の生活MMO do のように。これらすべてをどのようにスケーリングするか、そしてスレッドの将来のパッケージグループで通信プロセスにどのようにできるかを考えてください。そうすることで、増加するワークロード/接続を管理する追加のプロセスを備えたサーバーを追加できます。