1

サーバーとして機能するクラス オブジェクトがあります。どこからでもリクエストを受信し、そのリクエストをリクエスト キューにプッシュします ( Producer)。これで、リクエスト キューからリクエストをポップし、リクエストを提供する適切なクラス メソッドを呼び出すリクエストに基づいて実行中のコンシューマ スレッドがあります。これで、キューからのリクエストの消費と適切な関数の起動が同期的に実行されます。私が望むのは、消費者スレッドがキューからリクエストをポップアップし、適切な関数を非同期的に起動して、消費者がキューから次のリクエストをすぐにポップできるようにすることです。

私がこれで試した解決策の 1 つは、消費者がキューから要求をポップアップしboost::thread、新しいスレッドで適切な関数を作成して開始することです。スレッド ポインターを保存しstd::vectorただけでなく、 も試しboost::thread_groupました。ここまでは順調ですね。しかし、このソリューションには問題があります。

150 を超えるリクエストを送信すると、150 を超えるスレッドが存在し、その後、 pthread新しいスレッドが作成されず、エラーが発生します"pthread_create: Resource temporarily unavailable"。これは、現在のプロセスのスタックが不足しているため、新しいスレッドを作成できないことを意味すると考えられます。

質問 #1私のリクエスト ハンドラーには が含まれていませんwhile (1)。これらは何らかの作業を行って終了しているだけで、何も待機していません。そのため、最初のスレッドが処理を完了し、スレッド ハンドラー関数から終了したと予想しています。スレッドが処理を完了して終了した場合、これを考慮して、スタックからその内容をクリーンアップするべきではありませんか?

この問題の解決策の 1 つは、スレッドのスタック サイズを設定することですが、1000 スレッド後もこのエラーが発生します。

したがって、私の要件は、しばらくしてから完了したスレッドをクリーンアップする必要があることです (つまり、スレッド ポインターのベクトルが 100 を超えたとき、または 1 分ごとなど)。

質問 #2上で述べたように、新しいスレッドを起動する以外に、試してみるべき非同期関数呼び出しメカニズムは何ですか。boost::function+はboost::bind非同期ですか? これは私が言及した状況に対する良い解決策ですか? 私のシステムは 24 時間 365 日オンラインで、毎日 1000 件以上のリクエストを受け取っているとします。


更新 #1 それで、私の設計に 1 つの問題が見つかりました。質問 #1 で、私のリクエスト ハンドラーには単純な呼び出しだけが含まれていると述べましたが、これは真実ではないことがわかりました。サーバーからファイルを同期的にダウンロードしていますが、これは基本的にブロック操作です。ファイルを非同期でダウンロードする必要があります。

要求ハンドラーがブロッキング操作を行っていない場合、基になるシステムが同時に処理できないスレッドを作成しても意味がありません。

したがって、Alex が複数のコンシューマー スレッド (5 つあれば十分だと思います) を使用してキューからリクエストをポップし、非同期ファイルをダウンロードすることで問題が解決すると述べたように。

4

2 に答える 2

1

すでにBoostを使用していて、ファイルをダウンロードします。したがって、Boost.Asioをネットワーキングや、中央ディスパッチャーなどの他のすべてのマルチスレッド/非同期関連のものに使用するのは非常に自然なことです。

まず、スレッドのプールを作成し、それらに対してAsioディスパッチャーを実行することをお勧めします:ここのように。Asio非同期ネットワークを使用してファイルをダウンロードします:例はこちら。ファイルがダウンロードされたら、それを処理するだけです。

このアプローチは非常にスケーラブルであり、非同期ネットワークやマルチスレッド同期(かなりトリッキーなもの)について心配する必要はありません。Boost.Asioは、これを実現するための良い例を提供します。

于 2013-01-21T14:21:59.170 に答える
1

1 つの解決策は、複数のコンシューマー スレッドを用意することです。各スレッドは、キューからワーク アイテムをポップし、同期的に処理します。一度に複数のアイテムを処理しながら、同時実行を管理できます (オーバー サブスクリプションを回避できます)。また、ボトルネックの 1 つであると私が予測する、すべてのアイテムで新しいスレッドを起動するオーバーヘッドを取り除きます。

キューが複数のコンシューマー向けに設計されていることを確認する必要があります。

この実装を使用したことはありませんが、スレッドプールが役立つ場合があります。

于 2013-01-21T13:12:39.717 に答える