1

私はクライアント - 単一のクライアントとの永続的な接続を備えた 10 台のサーバーを備えたサーバー アーキテクチャを持っています。ソフトウェアは C++ で記述されており、boost asio ライブラリを使用しています。すべての接続は初期化フェーズで作成され、実行中は常に開いています。クライアントが何らかの情報を必要とする場合、すべてのサーバーにリクエストを送信します。各サーバーは、必要な情報とクライアントへの回答を見つけます。

クライアントには、すべてのソケットからのメッセージの受信を担当する 1 つのスレッドがあります。特に、io_services各ソケットから 1 つと async_read を 1 つだけ使用します。

メッセージがソケットの 1 つに到着すると、async_readメッセージのヘッダーである最初の N ビットをread読み取り、(同期) を使用して残りのメッセージを読み取る関数を呼び出します。サーバー側には、ヘッダーと残りのメッセージが単一write(同期) で送信されます。

その後、アーキテクチャは正常に動作しますが、同期readに通常よりも時間がかかる場合があることに気付きました (~0.24 秒)。が既にヘッダーを読み取ったときに同期readが呼び出されるため、理論的にはデータを読み取る準備ができています。async_readまた、サーバーを 10 台ではなく 1 台だけ使用すると、この問題は発生しないことがわかりました。さらに、この問題はメッセージの次元のために発生していないことに気付きました。

io_serviceが10 個すべてを処理できないために問題が発生する可能性はありasync_readますか? 特に、すべてのソケットが同時にメッセージを受信するとio_service、キューを管理する時間が失われ、同期が遅くなる可能性がありますreadか?

プロジェクトから抽出するのが難しいため、コードを投稿していませんが、私の説明が理解できない場合は、例を書くことができます。

ありがとうございました。

4

2 に答える 2

1

1) async.read 完了ハンドラーが呼び出されたとき、それは一部のデータが利用可能であることを意味するのではなく、その時点で利用可能なすべてのデータが既に読み取られていることを意味します(制限する完了条件を指定しない限り)。したがって、後続の sync.read は、さらにデータが到着するまで待機する場合があります。

2) 完了ハンドラーをブロックするのは悪い考えです。実際には、他のすべての完了ハンドラーとそれに投稿された他のファンクターをブロックするからですio_service。デザインの変更を検討してください。

于 2012-12-07T18:17:26.067 に答える
1

非同期設計を行う場合は、いくつかの同期部分を混ぜないでください。すべての同期読み取りと書き込みを非同期のものに置き換えます。読み取りと書き込みの両方がスレッドをブロックしますが、非同期バリアントはブロックしません。

さらに、ヘッダーを読み取った後に予想されるバイト数が正確にわかっている場合は、正確にそのバイト数を要求する必要があります。

わからない場合は、async_read_some予想される最大のメッセージのサイズのシングルを選ぶことができます. async_read_some実際に読み取られたバイト数が通知されます。

于 2012-12-08T19:17:24.343 に答える