これは、以前と同じ種類の質問です。
node.jsゲームの試合ごとに子プロセスを使用する必要があるかどうかを尋ねています。
しかし、以前は非常に重要な詳細を含めることを怠っていたことに気づきました。
このゲームでは、プレイヤーは特定の限られた方法でゲームルールを操作できます。ただし、これでも無限ループ/メモリリーク/ストールおよびクラッシュが発生する可能性があります。
マッチごとに1つのプロセスがスケーラブルで合理的なアイデアですか?
これは、以前と同じ種類の質問です。
node.jsゲームの試合ごとに子プロセスを使用する必要があるかどうかを尋ねています。
しかし、以前は非常に重要な詳細を含めることを怠っていたことに気づきました。
このゲームでは、プレイヤーは特定の限られた方法でゲームルールを操作できます。ただし、これでも無限ループ/メモリリーク/ストールおよびクラッシュが発生する可能性があります。
マッチごとに1つのプロセスがスケーラブルで合理的なアイデアですか?
1つのゲームプロセスがすべてのメモリまたはCPUを消費する可能性がある場合、これはスケーラブルではありません。サーバーが8コアのマシンの場合、8つのゲームですべてのCPU時間がかかる可能性があります。プロセスを監視し、必要に応じてプロセスを強制終了する以外に、できることは何もありません。ただし、top
サーバーが不安定になる可能性があります。
さて、そもそもこのようなことを防ぐことができれば(私にとってはより良い考えのように聞こえます)、それは実行可能です。各プロセスには30MB以上のメモリが必要になるため、数百台ごとに強力なサーバーが必要になります。例についてはhttp://site.nodester.comを見てください。これらは、単一のマシンで約600のプロセスを実行しているようです。彼らのソフトウェアスタックもオープンソースです:https ://github.com/nodester/nodester
ノードv0.8は、分離(シェアードナッシングスレッド)をもたらします。これは、おそらく子プロセスよりも少ないリソースを使用します。
これに対するより「深刻な」解決策は、 OpenVZのようなある種の仮想化を使用して、リソース制限を設定し、仮想サーバーのプールを利用可能な状態に保つことです。すべてのゲームが独自の仮想化を取得します。見た目ほど重くはなく、サーバーあたり最大18 MBのオーバーヘッドがあり、マシンあたり数百をホストできますが、セットアップははるかに複雑です。
簡単な答えはノーです、それはスケーリングしません!
長い答え
まず、スケーラビリティについて見てみましょう。私はウィキペディアによって提案された定義を採用しています。「スケーラビリティとは、システム、ネットワーク、またはプロセスが、増大する作業量を適切に処理する能力、またはその増大に対応するために拡張できる能力です。」
プロセスの1つがスケジューラーによって許可されたCPUを消費する可能性がある場合(Linuxスケジューラーの詳細)、システムは「適切な方法」でスケーリングされません。したがって、スケーラビリティに必要なのは、上記のRicardo Tomasiによって提案されたセットアップであり、すべての一致で独自のVMが必要になります。しかし、それは優雅ではなく、コストを考慮すると、これは実行可能な解決策ではありません。
システムがスケーリングしない理由の問題は、その背後にあるアルゴリズムです。アーキテクチャはそれを修正できませんが、アルゴリズムを修正する必要があります。
アルゴリズムを修正するためのオプション
また、アルゴリズムが修正されている場合でも、一致ごとにプロセスを生成すると、限られたRAMリソースのMBが消費され、スケーラビリティの意味で適切ではありません。
アクターモデルは間違いなくスケーラビリティを提供するはずだと思います。
おそらく、すべてのプロセスのバランスを取り、制御し、イベントを追跡するためのマスタープロセスが必要になります。アクターモデルを使用すると、マシンのネットワーク全体にスケールアウトでき、実際にはピアツーピアクラスターを作成することもできます。ただし、必要に応じて、認証にRSAキーを使用する必要がある場合があります。プロセスが接続するのを待っている単一のマスターから始めて、ワーカースケルトンを実装し、物事の制御側を実装する方法を確認することをお勧めします。初心者のために2人のワーカーでマスターに固執すると、デバッグが簡単になります。
Webフロントエンドの場合は、Nginxなどのプロキシを使用することもできます。このプロキシはマスターを呼び出し、マスターが新しいクライアントをどこに転送するかを指示します。UIモジュールを実装し、ワーカー内から使用する必要があると思います。つまり、マスターはUIを提示せず、ワーカーはさまざまなポートでリッスンしますが、Nginxはそれをユーザーから隠し(URLバーにポートは表示されません)、RESTfulAPIを上に実装することもできます。それも。
ここで議論することが複数あります。
何人のプレイヤーが試合に接続できますか?
どんなデータベースを使っていますか?高速書き込みがありますか?
プロセスを再開することが最後の解決策です。すべてが速く行われるはずのゲームがあり、プロセスを再開すると、プレーヤーがプロセスに再接続するまでに数秒かかるためです。
試合ごとに1つのプロセスがスケーラブルだとは思いません。たとえば、同時に50.000の試合がある場合はどうなりますか?より良い解決策は、子プロセスの一致を2つの基準でグループ化することです:
a)一致ID(ある種のシャーディングアルゴリズム)
b)より多くのプレーヤーがポップアップして別のプロセスをスピンする場合(またはそれ以上) )、プレーヤーの数に基づきます。
ゲームでいくつかのテストを行う前に、何をすべきかを決めるのは本当に難しいです。実際にテストして、いくつかの実際の一致(CPUが「消費」する量、メモリ)がどのように動作するかを確認し、データに基づいて分析を行う必要があります。プロジェクトにもよるので、こういう状況でどうしたらいいのか、正確には言えません。
あなたのゲームが何をするのかわからないので、これは答えるのが難しい質問です...
クラッシュすると、すべてのゲームがクラッシュするので、複数のプロセスを用意することをお勧めします。
しかし、私はあなたが複数のプロセスを持つべきである他の正当な理由を見ていません。(多分、巨大なDBトランザクション、巨大なファイルの処理などの大量のブロック操作...など)
@Samyak Bhutaが言ったように、永久に使用することも、クラスター化してプロセスを再開することもできます。これにはmonitを使用しています