14

C++ 学習プロジェクトの一環として、単純なマルチプレイヤー ゲームを作成したいと考えています。

せっかくなので、出来立てではなく、しっかりやっていきたいなと思いました。

私の理解が正しければ、Apache は Thread-per-connection アーキテクチャを使用しますが、nginx はイベントループを使用し、着信接続専用のワーカー[x]を使用します。より高い同時実行レベルをサポートしているため、nginx の方が賢明だと思います。右?

私もこの巧妙な類推に出くわしましたが、それが私の状況に適用できるかどうかはわかりません. この類推はまた、非常に理想主義者のようです。コンピューターが 100% の CPU で実行されているのを見たことはほとんどありません (無数の Chrome タブが開いていて、Photoshop とその他のものが同時に実行されていても)

また、ユーザーが使用するスレッドの数を尋ねた SO 投稿 (どういうわけか私の履歴から消えた) に出くわしましたが、その答えの 1 つは、約 700 スレッド、最大 10,000 スレッドであっても完全に許容できるというものでした。ただし、この質問はJVMに関連していました。

では、約 5,000 ユーザーの架空のユーザー ベースを見積もってみましょう。どのアプローチが「最も同時」であるべきですか?

  1. すべてを単一のスレッドで実行するリアクター パターン。
  2. スレッドプールを使用したリアクター パターン (おおよそ、スレッド プールの大きさはどのくらいですか?
  3. 接続ごとにスレッドを作成してから、接続が閉じるスレッドを破棄します。

オプション 2 が私にとって最良の解決策のように聞こえることは認めますが、私はこれらすべてについて非常に環境に配慮しているため、少し素朴で明らかな欠陥を見落としている可能性があります。また、実装するのはかなり難しいようです。

PS: POCO C++ Librariesの使用を検討しています。代替ライブラリ ( boostなど) を提案しても問題ありません。しかし、多くの人は、POCO のライブラリは非常にクリーンで理解しやすいと言っています。ですから、私はそれを使用することをお勧めします。そうすれば、私が使用しているものの使用方法について学ぶことができます。

4

5 に答える 5

11

リアクティブ アプリケーションは、正しく記述されていれば、確実にスケーリングが向上します。これの意味は

  • リアクティブ スレッドでブロックしない:
    • ブロッキングはサーバーのパフォーマンスを著しく低下させます。通常、少数のリアクティブ スレッドを使用するため、ブロッキングもすぐにデッドロックを引き起こす可能性があります。
    • これらはブロックできるためミューテックスがないため、共有された可変状態はありません。共有状態が必要な場合は、1 つのスレッドのみが状態にアクセスできるように、アクターなどでラップする必要があります。
  • リアクティブ スレッド内のすべての作業は、CPU バウンドにする必要があります
    • すべての IO は非同期にするか、別のスレッド プールで実行する必要があり、結果はリアクターにフィードバックされます。
    • これは、先物またはコールバックのいずれかを使用して応答を処理することを意味します。このスタイルのコードは、慣れていない場合や訓練されていない場合、すぐに保守できなくなる可能性があります。
  • リアクティブ スレッドでの作業はすべて小さくする必要があります
    • サーバーの応答性を維持するには、リアクター内のすべてのタスクを小さくする必要があります (時間によって制限されます)。
    • 8 コアのマシンでは、完了するまで他の作業が開始されないため、8 つの長いタスクを同時に到着させることはできません。
    • タスクに時間がかかる可能性がある場合は、分割する必要があります (協調的マルチタスク)

リアクティブ アプリケーションのタスクは、オペレーティング システムではなくアプリケーションによってスケジュールされます。そのため、タスクは高速になり、メモリ使用量が少なくなります。リアクティブ アプリケーションを作成するときは、問題のドメインをよく知っているため、オペレーティング システムがブロック方式で同じ作業を行うスレッドをスケジュールするよりも、このタイプの作業をうまく整理してスケジュールできると言っているのです。

私はリアクティブ アーキテクチャの大ファンですが、コストがかかります。初めての C++ アプリケーションをリアクティブとして作成するかどうかはわかりませんが、通常は一度に 1 つのことを学ぼうとします。

リアクティブ アーキテクチャを使用することにした場合は、コードの設計と構造化に役立つ優れたフレームワークを使用しないと、スパゲッティになってしまいます。探すべきものは次のとおりです。

  • 仕事の単位は何ですか?
  • 新しい作品を追加するのはどれくらい簡単ですか? 外部イベント (ネットワーク要求など) からのみ取得できますか
  • 仕事を小さなチャンクに分割するのはどれくらい簡単ですか?
  • この作業の結果を処理するのはどれくらい簡単ですか?
  • ブロッキング コードを別のスレッド プールに移動し、結果を処理するのはどれくらい簡単ですか?

これには C++ ライブラリをお勧めできません。現在はScalaAkkaでサーバー開発を行っており、コードをクリーンに保つための優れた構成可能な futures ライブラリをすべて提供しています。

C++ を学習し、どちらを選んでも幸運を祈ります。

于 2013-07-12T13:31:45.700 に答える
6

オプション 2 は、ハードウェアを最も効率的に占有します。これは古典的な記事で、10 年前のものですが、まだ良いものです。

http://www.kegel.com/c10k.html

同時実行性と非同期待機を備えたアプリケーションを構築するための最近の最適なライブラリの組み合わせは、Boost Thread と Boost ASIO です。C++11std threadライブラリを試すこともできますstd mutex(ただし、多くの場合、Boost ASIO はミューテックスよりも優れています。常に同じスレッドにコールバックするだけで、保護された領域は必要ありません)。に近づかないでstd futureください。壊れているためです。

http://bartoszmilewski.com/2009/03/03/broken-promises-c0x-futures/

スレッド プール内の最適なスレッド数は、CPU コアあたり 1 スレッドです。8コア→8スレッド。さらに、スレッドプールのスレッドがブロッキング操作を呼び出す可能性があると思われる場合は、さらにいくつか追加することもできます。

于 2013-01-14T12:29:11.433 に答える
3

FWIW、バージョン 1.5.1 以降、Poco はオプション 2 ( ParallelReactor ) をサポートしています

于 2013-02-04T05:09:44.993 に答える
1

あなたがリンクした類推(およびそのコメント)が示唆するように。これは多少アプリケーションに依存します。ここで構築しているのはゲームサーバーです。それを分析しましょう。

ゲーム サーバーは (一般的に) 多くの I/O を実行し、計算は比較的少ないため、100% CPU アプリケーションにはほど遠いものです。一方、それらは通常、何らかのデータベース (「ゲーム世界」モデル) の値も変更します。すべてのプレイヤーがこのデータベースへの読み取りと書き込みを作成します。これはまさに類推の交差問題です。

そのため、個別のスレッドで I/O を処理することで得られるものもありますが、別のスレッドが同じデータベースにアクセスし、そのロックを待機することで失われることもあります。

そのため、状況ではオプション 1 または 2 のいずれかが受け入れられます。スケーラビリティの理由から、オプション 3 はお勧めしません。

于 2013-01-14T12:26:27.880 に答える
1

オプション 2 が最適だと思います。プールサイズの調整に関しては、プールは適応的であるべきだと思います。より多くのスレッドを生成し (いくつかの高いハード リミットを使用)、アクティビティが少ないときに過剰なスレッドを削除できるはずです。

于 2013-01-14T11:59:41.173 に答える